use*_*245 2 python class-variables python-3.x
我正在使用类和子类作为应用程序.对于每个类,super和sub,都有一个名为的变量类label.我希望label超类的变量默认为类名.例如:
class Super():
label = 'Super'
class Sub(Super):
label = 'Sub'
Run Code Online (Sandbox Code Playgroud)
而不是手动为每个类输出变量,是否可以从超类中的类名派生变量并自动为子类填充?
class Super():
label = # Code to get class name
class Sub(Super)
pass
# When inherited Sub.label == 'Sub'.
Run Code Online (Sandbox Code Playgroud)
原因是这将是默认行为.我也希望如果我能获得默认行为,我可以稍后通过指定备用行为来覆盖它label.
class SecondSub(Super):
label = 'Pie' # Override the default of SecondSub.label == 'SecondSub'
Run Code Online (Sandbox Code Playgroud)
我尝试过使用__name__,但这不起作用,只是给了我'__main__'.
我想label在@classmethod方法中使用类变量.所以我希望能够在不必实际创建Super()或Sub()对象的情况下引用该值,如下所示:
class Super():
label = # Magic
@classmethod
def do_something_with_label(cls):
print(cls.label)
Run Code Online (Sandbox Code Playgroud)
您可以self.__class__.__name__在标签中作为财产返回
class Super:
@property
def label(self):
return self.__class__.__name__
class Sub(Super):
pass
print Sub().label
Run Code Online (Sandbox Code Playgroud)
或者你可以在__init__方法中设置它
def __init__(self):
self.label = self.__class__.__name__
Run Code Online (Sandbox Code Playgroud)
这显然只适用于实例化的类
要访问类方法中的类名,您只需要调用__name__它cls
class XYZ:
@classmethod
def my_label(cls):
return cls.__name__
print XYZ.my_label()
Run Code Online (Sandbox Code Playgroud)
这个解决方案也可能起作用(来自/sf/answers/953740091/)
class classproperty(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, owner_self, owner_cls):
return self.fget(owner_cls)
class Super(object):
@classproperty
def label(cls):
return cls.__name__
class Sub(Super):
pass
print Sub.label #works on class
print Sub().label #also works on an instance
class Sub2(Sub):
@classmethod
def some_classmethod(cls):
print cls.label
Sub2.some_classmethod()
Run Code Online (Sandbox Code Playgroud)
您可以使用描述符:
class ClassNameDescriptor(object):
def __get__(self, obj, type_):
return type_.__name__
class Super(object):
label = ClassNameDescriptor()
class Sub(Super):
pass
class SecondSub(Super):
label = 'Foo'
Run Code Online (Sandbox Code Playgroud)
演示:
>>> Super.label
'Super'
>>> Sub.label
'Sub'
>>> SecondSub.label
'Foo'
>>> Sub().label
'Sub'
>>> SecondSub().label
'Foo'
Run Code Online (Sandbox Code Playgroud)
如果class ThirdSub(SecondSub)应该有ThirdSub.label == 'ThirdSub'而不是ThirdSub.label == 'Foo',你可以做更多的工作。label在类级别分配将被继承,除非您使用元类(这比它的价值要麻烦得多),但我们可以让label描述符查找_label属性:
class ClassNameDescriptor(object):
def __get__(self, obj, type_):
try:
return type_.__dict__['_label']
except KeyError:
return type_.__name__
Run Code Online (Sandbox Code Playgroud)
演示:
>>> class SecondSub(Super):
... _label = 'Foo'
...
>>> class ThirdSub(SecondSub):
... pass
...
>>> SecondSub.label
'Foo'
>>> ThirdSub.label
'ThirdSub'
Run Code Online (Sandbox Code Playgroud)
元类在这里可能很有用。
class Labeller(type):
def __new__(meta, name, bases, dct):
dct.setdefault('label', name)
return super(Labeller, meta).__new__(meta, name, bases, dct)
# Python 2
# class Super(object):
# __metaclass__ = Labeller
class Super(metaclass=Labeller):
pass
class Sub(Super):
pass
class SecondSub(Super):
label = 'Pie'
class ThirdSub(SecondSub):
pass
Run Code Online (Sandbox Code Playgroud)
免责声明:为您的类提供自定义元类时,您需要确保它与任何类在其祖先中使用的任何元类兼容。通常,这意味着确保您的元类继承自所有其他元类,但这样做并非易事。在实践中,元类并不常用,所以通常只是子类化的问题type,但这是需要注意的。
| 归档时间: |
|
| 查看次数: |
1781 次 |
| 最近记录: |