Dynamic Strings: A module for easy replacements¶
Python file for a dynamic string
This module offers an implementation of a class (DynamicString) that behaves like a string 
but can be built using different common pieces so it is possible to perform simultaneos
substitutions on the string.
EXAMPLES:
sage: from ajpastor.misc.dynamic_string import *
- TODO:
- Complete the Examples section of this documentation 
 
AUTHORS:
Antonio Jimenez-Pastor (2016-10-01): initial version
- 
class ajpastor.misc.dynamic_string.DynamicString(template, arguments, escape='_')¶
- Bases: - object- Class for dynamic strings, developed to make easier the substitution of elements through the string. - This class allows the user to manage strings dynamically, which means, being able to make substitutions through the whole string simultaneously, or iterated substitutions in a simple and consistent manner. - For doing so, this string works with “templates”. The string is defined as a main structure for the main message where some escape characters may be used to mark where the substitutions will be made. - For example, if we have the name of a function - exp(x) + 7x^2 - sin(x), we may want to compute a composition with- 3ysin(y). Then we could create a- DynamicStringwith the command- DymanicString("exp(_1) + 7_1^2 - sin(_1)", ["x"])- This command creates the object that can be read as the first name. However, substituing the - xby the new name, is easy, since we have marked where- xappeared originally.- INPUT:
- template: a string with the main structure for the Dynamic String. This string may contain the escape character (see below) followed by integers to mark where each of the arguments will be replaced.
- arguments: a list or tuple containing the arguments for this DynamicString. A- ValueErroris raised if the number of arguments is too small.
- escape: a character to mark how the arguments are introduced. By default, it takes the value- '_'.
 
 - EXAMPLES: - sage: from ajpastor.misc.dynamic_string import * sage: s = DynamicString("_1 + _2_1", ["a","b"]); s a + ba sage: s.replace('a', 'c') c + bc sage: t = DynamicString("+1 - +2", [s, 'x'], '+'); t a + ba - x sage: t + s # concatenation a + ba - xa + ba sage: (t+s).replace('a', 'x') x + bx - xx + bx - This class does not allow a as escape character anything but strings of length 1: - sage: DynamicString("##1 + ##2##1", ['a','b'], escape='##') Traceback (most recent call last): ... TypeError: The escape character must be of type 'str' with length 1 or 'chr'. Received <class 'str'>: ## sage: DynamicString("11 + 12", ['a','b'], escape=1) Traceback (most recent call last): ... TypeError: The escape character must be of type 'str' with length 1 or 'chr'. Received <class 'sage.rings.integer.Integer'>: 1- Although numbers can be used as escape characterers if set as strings: - sage: DynamicString("11 + 12", ['a','b'], escape='1') a + b - The method also checks that the number of arguments are enough to perform the substitution: - sage: DynamicString("_3 + _1", ['a','b']) Traceback (most recent call last): ... ValueError: Invalid number of arguments: required at least 3, provided 2 - 
change_argument(new_argument, index=1)¶
- Method to change the arguments of a - DynamicString.- This method allows the user to set a new value for a particular argument. The user must provide the new value (that has to be valid for an argument, see - DynamicString) and an index that has to be bounded in the number of required.- The method also allows a list of new arguments that has to be long enough to be valid. Then the argument - indexwill be ignored and all arguments will be changed.- This method clean the cache for the method - real().- INPUT:
- new_argument: a valid argument or a list (long enough) for all the arguments
- index: index of the argument that will be changed. Ignored if- new_argumentis a list. By defualt its value is “1”
 
 - EXAMPLES: - sage: from ajpastor.misc.dynamic_string import * sage: s = DynamicString("exp(_1) + cos(_1_2)", ['x','y']); s exp(x) + cos(xy) sage: s.change_argument("a"); s exp(a) + cos(ay) sage: s.change_argument(["x","b"]); s exp(x) + cos(xb) - The new argument can be a DynamicString: - sage: t = DynamicString("exp(_1)", ["c"]) sage: s.change_argument(t, 2); s exp(x) + cos(xexp(c)) - However, changing the argument of - swill not change the arguments of the inner String:- sage: s.change_argument("y"); s exp(y) + cos(yexp(c)) sage: t.change_argument("t"); s exp(y) + cos(yexp(t)) - Providing a string that is not valid (see method - is_string()) will cause a- TypeError:- sage: s.change_argument(1, 2) Traceback (most recent call last): ... TypeError: No valid argument for a DynamicString: only strings and DynamicStrings are valid sage: s.change_argument([x, "t"]) Traceback (most recent call last): ... TypeError: No valid arguments for a DynamicString: only strings and DynamicStrings are valid - Also, a bad number of arguments or index will raise a - ValueError:- sage: s.change_argument(["1","2","3"]); s exp(1) + cos(12) sage: s.change_argument(["x"]) Traceback (most recent call last): ... ValueError: Invalid number of arguments: required at least 2, provided 1 sage: s.change_argument("x", 3) Traceback (most recent call last): ... ValueError: Invalid index: the index has to be between 1 and 2. Got: 3 sage: s.change_argument("x", 0) Traceback (most recent call last): ... ValueError: Invalid index: the index has to be between 1 and 2. Got: 0 sage: s.change_argument("x", -1) Traceback (most recent call last): ... ValueError: Invalid index: the index has to be between 1 and 2. Got: -1 
 - 
m_replace(to_replace, deep=False)¶
- Method to perform several replacements simultaneously. - This method do exactly the same as ‘self.replace(key, value) for all (key,value) in to_replace but all at once, avoiding that one substitution affects the next one. This method returns always a new DynamicString with the replacements already done. - INPUT:
- to_replace: dictionary with the pairs (pattern, out) to replace in- self.
- deep: this do the same as the argument- deepon- replace().
 
 - EXAMPLES: - sage: from ajpastor.misc.dynamic_string import * sage: s = DynamicString("_1 + exp(_2) - _3", ["x","y","e"]) sage: s.m_replace({"x": "y", "y": "x"}) y + eyp(x) - e sage: s.replace("x", "y").replace("y", "x") x + exp(x) - e sage: s.m_replace({"x": "y", "y": "x"}, True) y + exp(x) - e 
 - 
nargs()¶
- Getter for the number of arguments for a DynamicString. - This method returns the exact amount of arguments that this DynamicString has. This method does not iterate through inner DynamicStrings since the substitution is independent in each case. - EXAMPLES: - sage: from ajpastor.misc.dynamic_string import * sage: DynamicString("exp(x)",[]).nargs() 0 sage: DynamicString("exp(_1)", ['x']).nargs() 1 sage: DynamicString("_1 + _2", [DynamicString("exp(_1)", ["x"]), "a"]).nargs() 2 sage: (DynamicString("_1", ["exp(x)"]) + DynamicString("_1", ["y"])).nargs() 2 
 - 
real()¶
- Method to compute the current representation of the DynamicString - This method computes the actual string object that the Dynamic String is currently representing. This method is cached, so calling it several times will not repeat the computations. However, the user can call the method - clean()for removing the cached result.- This cached result is also cleaned automatically when using the method - change_argument().- EXAMPLES: - sage: from ajpastor.misc.dynamic_string import * sage: s = DynamicString("exp(_1)", ["x"]); s.real() 'exp(x)' sage: s.change_argument("y"); s.real() 'exp(y)' sage: s.real() # no computations done 'exp(y)' - This method is not affected by the method - replace():- sage: s.replace("x", "l") elp(y) sage: s.real() 'exp(y)' - This method returns always the same as casting the elemtn to a string: - sage: str(s) == s.real() True 
 - 
replace(pattern, out, deep=False)¶
- Replacing method for DynamicStrings - This method performs a similar operation as the method - str.replace(). However, this method splits the string into the template and the arguments perfoming the substitution in both separately and then combining them together into a final DynamicString.- If the required pattern includes the escape character, the method will raise an error. - INPUT:
- pattern: the string we want to change in- self.
- out: the new string to put where- patternis found.
- deep: extra argument that allows the user to only perform substitutions within the arguments. The default value is- False.
 
 - EXAMPLES: - sage: from ajpastor.misc.dynamic_string import * sage: s = DynamicString("_1 and _2", ["a", "b"]) sage: s.replace('a', 'x') x xnd b sage: s.replace('a', 'x', True) x and b sage: t = DynamicString("exp(_1, _2) - a", ["A", "a"]) sage: s.change_argument(t, 2); s a and exp(A, a) - a sage: s.replace("a", "P") P Pnd exp(A, P) - P sage: s.replace("a", "P", True) P and exp(A, P) - a 
 
- 
ajpastor.misc.dynamic_string.dreplace(element, pattern, out, deep=False)¶
- Enhanced “replace” method. - This function is equivalent to the - replacemethod of the- strclass when both- elementand- outare strings. However, this method mix together the use of- DynamicStringand strings.- INPUT:
- element: a string or- DynamicStringwhere we want to replace- pattern.
- pattern: a string with the pattern to replace in- element.
- out: a string or- DynamicStringthat will be put in the places where- patternappears in- element.
- deep: in case- elementis a- DynamicString, this argument is equivalent to that in method- DynamicString.replace().
 
- OUTPUT:
- If - elementand- outare both strings, then the method return the equivalent string after the replacement.
- Otherwise, this method returns a - DynamicString.
 
 - EXAMPLES: - sage: from ajpastor.misc.dynamic_string import * sage: s = DynamicString("exp(_1)", ["x"]) sage: t = dreplace("testing string", "string", s); t testing exp(x) sage: isinstance(t, DynamicString) True sage: u = dreplace("testing string", "s", " a "); u 'te a ting a tring' sage: isinstance(u, DynamicString) False sage: v = dreplace(s, "x", "y"); v eyp(y) sage: str(v) == str(s.replace("x", "y")) True - This method raise an error if - elementis not a string or a- DynamicString:- sage: dreplace(123, "1", "2") Traceback (most recent call last): ... TypeError: No string given. Impossible to replace string 
- 
ajpastor.misc.dynamic_string.m_dreplace(element, to_replace, deep=False)¶
- Method that replace simultaneously patters in a string. - This method perfoms a simoultanously substitution on - element(if it is either a string or a- DynamicString) patterns that can be found in- to_replace. This is equivalent, in the case of- DynamicString, to the method- DynamicString.m_replace().- INPUT:
- element: string or- DynamicStringto perform the replacement.
- to_replace: dictionary with entries- (pattern : out)to be replaced.
- deep: see argument- deepin method- DynamicString.replace().
 
- OUTPUT:
- If - elementand all the entries in- to_replaceare strings, this method returns a string object after performing the substitution.
- Otherwise, this method returns a new DynamicString. 
 
 - EXAMPLES: - sage: from ajpastor.misc.dynamic_string import * sage: s = DynamicString("exp(_1)", ["a"]) sage: t = "a + b" sage: u = m_dreplace(t, {"a": "b", "b" : "a"}); u 'b + a' sage: isinstance(u, DynamicString) False sage: v = m_dreplace(s, {"a":"b", "x": "y"}); v eyp(b) sage: isinstance(v, DynamicString) True sage: v.nargs() 1 sage: m_dreplace(s, {"a":"b", "x": "y"}, True) exp(b) - This method raise an error if - elementis not a string or a- DynamicString:- sage: m_dreplace(123, {"1": "2", "2": "3"}) Traceback (most recent call last): ... TypeError: No string given. Impossible to replace multiple strings 
- 
ajpastor.misc.dynamic_string.is_string(element)¶
- Method that checks whether an object can be considered a string. - This method check that the type of the input is either - stror a- DynamicStringso it is valid for use for the latter class.- INPUT:
- element: the object to be checked
 
 - EXAMPLES: - sage: from ajpastor.misc.dynamic_string import * sage: is_string(1) False sage: is_string("%d" %1) True sage: is_string(DynamicString("_1 + _2", ['a', 'b'])) True