parameters.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. """Thread-safe global parameters"""
  2. from .cache import clear_cache
  3. from contextlib import contextmanager
  4. from threading import local
  5. class _global_parameters(local):
  6. """
  7. Thread-local global parameters.
  8. Explanation
  9. ===========
  10. This class generates thread-local container for SymPy's global parameters.
  11. Every global parameters must be passed as keyword argument when generating
  12. its instance.
  13. A variable, `global_parameters` is provided as default instance for this class.
  14. WARNING! Although the global parameters are thread-local, SymPy's cache is not
  15. by now.
  16. This may lead to undesired result in multi-threading operations.
  17. Examples
  18. ========
  19. >>> from sympy.abc import x
  20. >>> from sympy.core.cache import clear_cache
  21. >>> from sympy.core.parameters import global_parameters as gp
  22. >>> gp.evaluate
  23. True
  24. >>> x+x
  25. 2*x
  26. >>> log = []
  27. >>> def f():
  28. ... clear_cache()
  29. ... gp.evaluate = False
  30. ... log.append(x+x)
  31. ... clear_cache()
  32. >>> import threading
  33. >>> thread = threading.Thread(target=f)
  34. >>> thread.start()
  35. >>> thread.join()
  36. >>> print(log)
  37. [x + x]
  38. >>> gp.evaluate
  39. True
  40. >>> x+x
  41. 2*x
  42. References
  43. ==========
  44. .. [1] https://docs.python.org/3/library/threading.html
  45. """
  46. def __init__(self, **kwargs):
  47. self.__dict__.update(kwargs)
  48. def __setattr__(self, name, value):
  49. if getattr(self, name) != value:
  50. clear_cache()
  51. return super().__setattr__(name, value)
  52. global_parameters = _global_parameters(evaluate=True, distribute=True, exp_is_pow=False)
  53. @contextmanager
  54. def evaluate(x):
  55. """ Control automatic evaluation
  56. Explanation
  57. ===========
  58. This context manager controls whether or not all SymPy functions evaluate
  59. by default.
  60. Note that much of SymPy expects evaluated expressions. This functionality
  61. is experimental and is unlikely to function as intended on large
  62. expressions.
  63. Examples
  64. ========
  65. >>> from sympy import evaluate
  66. >>> from sympy.abc import x
  67. >>> print(x + x)
  68. 2*x
  69. >>> with evaluate(False):
  70. ... print(x + x)
  71. x + x
  72. """
  73. old = global_parameters.evaluate
  74. try:
  75. global_parameters.evaluate = x
  76. yield
  77. finally:
  78. global_parameters.evaluate = old
  79. @contextmanager
  80. def distribute(x):
  81. """ Control automatic distribution of Number over Add
  82. Explanation
  83. ===========
  84. This context manager controls whether or not Mul distribute Number over
  85. Add. Plan is to avoid distributing Number over Add in all of sympy. Once
  86. that is done, this contextmanager will be removed.
  87. Examples
  88. ========
  89. >>> from sympy.abc import x
  90. >>> from sympy.core.parameters import distribute
  91. >>> print(2*(x + 1))
  92. 2*x + 2
  93. >>> with distribute(False):
  94. ... print(2*(x + 1))
  95. 2*(x + 1)
  96. """
  97. old = global_parameters.distribute
  98. try:
  99. global_parameters.distribute = x
  100. yield
  101. finally:
  102. global_parameters.distribute = old
  103. @contextmanager
  104. def _exp_is_pow(x):
  105. """
  106. Control whether `e^x` should be represented as ``exp(x)`` or a ``Pow(E, x)``.
  107. Examples
  108. ========
  109. >>> from sympy import exp
  110. >>> from sympy.abc import x
  111. >>> from sympy.core.parameters import _exp_is_pow
  112. >>> with _exp_is_pow(True): print(type(exp(x)))
  113. <class 'sympy.core.power.Pow'>
  114. >>> with _exp_is_pow(False): print(type(exp(x)))
  115. exp
  116. """
  117. old = global_parameters.exp_is_pow
  118. clear_cache()
  119. try:
  120. global_parameters.exp_is_pow = x
  121. yield
  122. finally:
  123. clear_cache()
  124. global_parameters.exp_is_pow = old