我有一个装饰器,它包装函数并生成类(出于比以下示例更好的原因)。这一切都有效,除了我希望能够设置type().
例如,
>>> class Animal:
... pass
...
>>> def linnean_name(genus, species):
... def _linnean_name(fn):
... class _Animal(Animal):
... binomial_name = (genus, species)
... def converse(self):
... fn()
... _Animal.__name__ = fn.__name__.title()
... _Animal.__module__ = fn.__module__
... return _Animal
... return _linnean_name
...
>>> @linnean_name('Vombatus', 'ursinus')
... def Wombat():
... print("Hello, I am a wombat.")
...
>>> sheila = Wombat()
>>> sheila.binomial_name
('Vombatus', 'ursinus')
>>> sheila.converse()
Hello, I am a wombat.
Run Code Online (Sandbox Code Playgroud)
一切都很好,但是
>>> type(sheila)
<class '__main__.linnean_name.<locals>._linnean_name.<locals>._Animal'>
Run Code Online (Sandbox Code Playgroud)
我希望看到的地方
<class '__main__.Wombat'>
Run Code Online (Sandbox Code Playgroud)
这就是原因
... _Animal.__name__ = fn.__name__.title()
... _Animal.__module__ = fn.__module__
Run Code Online (Sandbox Code Playgroud)
这似乎没有做任何特别有用的事情。我怎样才能做到这一点?
您正在寻找__new__. 它允许您指定新的类名并共享预定义行为的公共基类。您还可以通过定义更多基/基类等来创建 MixIn 类。
class Animal:
def talk(self):
print(f"Hello, I am {self}")
def __str__(self):
return f'{self.family} {self. spec}'
def __new__(cls, family, spec, *args, **kwargs):
cls_name = family.title() + spec.title()
bases = (cls,)
typ = type(cls_name, bases, {})
obj = object.__new__(typ)
#from here it's like __init__
#except you return the object instead of None
#obj is equal to self in the __init__ here
obj.family = family
obj.spec = spec
return obj
pass
sheila = Animal('Vombatus', 'ursinus')
sheila.talk()
Run Code Online (Sandbox Code Playgroud)
正如评论中提到的,您实际上不必使用类,__new__您只需拥有一个使用type. 然而,在我看来__new__更具可读性。
class Animal:
def talk(self):
print(f"Hello, I am {self}")
def __str__(self):
return f'{self.family} {self. spec}'
pass
def factory(family, spec, *args, **kwargs):
cls_name = family.title() + spec.title()
bases = (Animal,)
typ = type(cls_name, bases, {})
obj = typ(*args, **kwargs)
obj.family = family
obj.spec = spec
return obj
sheila = factory('Vombatus', 'ursinus')
print(type(sheila))
sheila.talk()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
144 次 |
| 最近记录: |