View in #code_tips_and_tricks on Slack
@ozzmeister00: Sooooooooo, I ran into something cool about Python today. init is called after the methods of a class are evaluated. So for example:
def __init__(self, val):
self.variable = val
>>> a = Thing('Ping')
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
TypeError: 'str' object is not callable
@ddevoe: “cool” or cool?
@passerby: well init can call other methods
@bob.w: Yeah, the class body is evaluated when the file is loaded at ‘compile time’. It can be altered by using a metaclass or a class decorator.
@jeff_hanna: How can we use this knowledge for evil?
@theodox: it has to work like this, so that
__init__ can call other class or instance methods. Otherwise you’d have to control it by moving the location of
__init__ around in the file
If you need to catch it at creation time is to override
__new__ already has the class body set. You need to get at it earlier than that if you want to mess with it.
@theodox: yes, but
__init__ so you could change what
__init__ has to work with
@bob.w: Very true.
That also operates on a per instance level. So you’d be doing the alteration each time a new instance is created, which could be what you want.
Most of the times I’ve wanted to mess with the class scope, I’ve wanted to do it for all instances, which is probably why my brain went to metaclasses and class decorators first.
in python3 you can even override the
__build_class__ function to mess with class creation much like overriding
__import__ can be used to change how the
import statement operates.
def __init__(self, start):
self._inner = start or self._inner
def __new__(cls, *args):
result = X.__new__(cls, *args)
result._inner = 999
hello = Y(None)
if you wanted to do something like recycle ids or timestamp objects you could do it there.
It’s goofy but it works
__new__ is like the super-minimal version of metaclassing
the only time I’ve every done it for realz is creating classes that inherit from
__new__ as well.
frozenset probably does as well, but I’ve never tried to subclass that one
the immutable builtins rely on
__new__ to do most of their initialization
@theodox: Python: Too Clever By Half™
@bob.w: Python: “You can do anything, but really should you?”
@adam.pletcher: I fucked with our import mechanics at work once and didn’t tell anyone about it. Might even still be in place, I’m not even sure, lol.
@passerby: i feel like every language has a few features where if you use them you should be questioning why
@covinator: Like using strings and MemberInfos in C# to get the value of fields via reflection.
weeps slowly in the corner
though when working with some more limited api;s like unity reflection can save your ass at times
but 99% of the time if you think reflection is the answer you fucked up