Jacob Solinsky writes: > What I had hoped to do was use a preamble code block to collect all of the > most common queries called by the mutate function in the local namespace, > for example > > C = 'bpgkdtszSZjCmnywh' > M = 'mn' > > > class Morpheme: > #stuff > > def preamble(self): > > ps = self.precedingmorpheme.form > ss = self.succeedingmorpheme.form > ssc = re.match(f'^[{C}]', self.succedingmorpheme.form) #Whether or not > the following morpheme is consonant initial > ssm = re.match(f'[{M}]$', self.precedingmorpheme.form) #Whether or not > the preceding morpheme is nasal final > > these local variables are used quite often in the mutate methods, of which > there are several dozen, so storing them by default saves a lot of > typing.
What you're asking for is basically a "Ruby block", AFAICS. This has been requested many times, but most of the senior Pythonistas consider that it leads to a very high risk of unreadable and/or buggy code at no gain in power (there are several ways to efficiently accomplish what you want to do, you just don't like them[1]), and few cases where it's more readable/less buggy. I think if you search "ruby block site:mail.python.org" you'll probably bring up the threads. You won't find a lot of encouraging discussion, I'm afraid. What I would do in your case is class Morpheme: class Preamble: def __init__(self, m): # "m" for "morpheme" self.ps = m.precedingmorpheme.form self.ss = m.succeedingmorpheme.form self.ssc = re.match(f'^[{C}]', m.succedingmorpheme.form) self.ssm = re.match(f'[{M}]$', m.precedingmorpheme.form) def mutate(): p = self.Preamble(self) # use p.ps, p.ss, etc It's a little less efficient, of course, because of overhead managing the Preamble objects. Another possibility would be to use properties, so that instead of *storing* these temporary variables on the Morpheme, they would be computed on the fly: class Morpheme: @property def ps(self): return self.precedingmorpheme.form @property def ss(self): return self.succeedingmorpheme.form @property def ssc(self): return re.match(f'^[{C}]', self.succeedingmorpheme.form) @property def ssm(self): return re.match(f'[{M}]$', self.precedingmorpheme.form) and so on. Then you can access them with "self.ps" etc in the mutate method. This might be considered elegant (although verbose in the Morpheme definition) if these properties are usually used only once per mutate call, and "expensive" properties like ssc and ssm are never called more than once. (If they are called multiple times, it's easy to create a cache.) Of course property accesses do add method call overhead, but they look nicer than method call syntax. On the other hand, if "many" properties are expensive, and "most" mutate methods use only a few of these, you could save runtime this way, since the expensive methods are called only as-needed. I don't understand the "need default value in __init__" issue, since "inject" implied to me that you initialize before use. But if that's a problem for ordinary attributes, I presume it'll be more annoying with properties because you have to write a method for it. So I don't know if this is helpful at all. Footnotes: [1] "I don't like it" is a sufficient reason to propose a change. I'm simply saying you have the *power* to do what you want. _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/