Say I have the following class in Python 2.7:
class X():
def __init__(self, alpha=1):
self.alpha = alpha
print self.alpha
def beta(self, gamma=1):
self.gamma = gamma
self.omega = self.alpha + self.gamma
print self.omega
I want to use the class definition to create another class definition with different default arguments, eg something like:
Y = f(X, alpha=2, gamma=2)
or
Y = f(X, __init__.alpha=2, beta.gamma=2)
which should be equivalent to:
class Y():
def __init__(self, alpha=2):
self.alpha = alpha
print self.alpha
def beta(self, gamma=2):
self.gamma = gamma
self.omega = self.alpha + self.gamma
print self.omega
Is it possible to do something like this in Python 2.7 (or 3?)?
(I know you can use the functools.partial
to do the equivalent for functions; so I was wondering if there was anything similar for classes)
You can write a function that creates classes for you:
def makeclass(alpha, gamma):
class C():
def __init__(self, alpha=alpha):
self.alpha = alpha
print self.alpha
def beta(self, gamma=gamma):
self.gamma = gamma
self.omega = self.alpha + self.gamma
print self.omega
return C
>>> X = makeclass(1, 1)
>>> Y = makeclass(2, 2)
>>> x = X() # X is the class, x is an instance
1
>>> x.beta()
2
>>> y = Y()
2
>>> y.beta()
4
This can be done, but it's a bit messy.
This code:
class Foo(base1, base2, ...):
bar = something
baz = something_else
def qux(self):
...
...is equivalent to this code, though I'm not sure this is correct if Foo
is a classic class:
Foo = type('Foo', (base1, base2, ...), {'bar': something, 'baz': something_else,
'qux': lambda self: ...})
So we can create classes on the fly, and attach custom method objects to them.
For your specific case, we need to make these calls (assuming you convert X into a new-style class by inheriting from object
). First, we extract methods from X and apply functools.partial
:
new_init = functools.partial(X.__init__.im_func, # Just X.__init__ in 3.x
alpha=2)
new_beta = functools.partial(X.beta.im_func, # Just X.beta in 3.x
gamma=2)
The im_func
attribute grabs the underlying function out of the unbound method object. In Python 3, there's no such thing as an unbound method, so we don't need to use this attribute; X.__init__
is just the function itself.
Next, we create the class:
Y = type('Y', (object,), {'__init__': new_init, 'beta': new_beta})
Unfortunately, we don't have any reasonable way of getting a list of the functions we need to redefine here. If we use dir()
we'll get a lot of irrelevant special attributes. We could use the class's __dict__
, but that won't include any inherited methods. I think we may need to search X.__mro__
for a fully correct listing of methods:
result = {}
for class_ in X.__mro__:
for name, value in class_.__dict__.items():
if name not in result:
result[name] = value
We also need to figure out which arguments to override in each case; inspect.getargspec()
is a good starting point for this, but it will not help much if any of the methods are variadic (ie if they take *args
or **kwargs
arguments).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.