Python Class 命名为 Class 变量
Python Class Name as Class Variable
我正在使用 classes 和 subclasses 的应用程序。对于每个 class,包括 super 和 sub,都有一个名为 label
的 class 变量。我希望超级 class 的 label
变量默认为 class 名称。例如:
class Super():
label = 'Super'
class Sub(Super):
label = 'Sub'
与其手动输入每个 class 的变量,是否可以从超级 class 中的 class 名称派生变量并自动填充subclasses?
class Super():
label = # Code to get class name
class Sub(Super)
pass
# When inherited Sub.label == 'Sub'.
原因是这将是默认行为。我也希望如果我可以获得默认行为,我可以稍后通过指定替代 label
.
来覆盖它
class SecondSub(Super):
label = 'Pie' # Override the default of SecondSub.label == 'SecondSub'
我试过使用 __name__
,但它不起作用,只给了我 '__main__'
。
我想在 @classmethod
方法中使用 class 变量 label
。所以我希望能够引用该值而不必实际创建 Super() 或 Sub() 对象,如下所示:
class Super():
label = # Magic
@classmethod
def do_something_with_label(cls):
print(cls.label)
您可以 return self.__class__.__name__
在标签中作为 属性
class Super:
@property
def label(self):
return self.__class__.__name__
class Sub(Super):
pass
print Sub().label
或者您可以在 __init__
方法中设置它
def __init__(self):
self.label = self.__class__.__name__
这显然只适用于实例化的 classes
要在 class 方法中访问 class 名称,您只需在 cls
上调用 __name__
class XYZ:
@classmethod
def my_label(cls):
return cls.__name__
print XYZ.my_label()
这个解决方案也可能有效(摘自 )
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()
您可以使用 descriptor:
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'
演示:
>>> Super.label
'Super'
>>> Sub.label
'Sub'
>>> SecondSub.label
'Foo'
>>> Sub().label
'Sub'
>>> SecondSub().label
'Foo'
如果 class ThirdSub(SecondSub)
应该有 ThirdSub.label == 'ThirdSub'
而不是 ThirdSub.label == 'Foo'
,您可以多做一些工作。在 class 级别分配 label
将被继承,除非你使用元 class (这比它的价值要麻烦得多),但我们可以让 label
描述符改为查找 _label
属性:
class ClassNameDescriptor(object):
def __get__(self, obj, type_):
try:
return type_.__dict__['_label']
except KeyError:
return type_.__name__
演示:
>>> class SecondSub(Super):
... _label = 'Foo'
...
>>> class ThirdSub(SecondSub):
... pass
...
>>> SecondSub.label
'Foo'
>>> ThirdSub.label
'ThirdSub'
metaclass 在这里可能会有用。
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
免责声明:在为您的 class 提供自定义元 class 时,您需要确保它与任何 [= 使用的任何元 class(es) 兼容16=] 在其祖先中。通常,这意味着确保您的元class 继承自所有其他元class,但这样做并不容易。在实践中,metaclasses 并不常用,所以它通常只是一个 subclassing type
的问题,但这是需要注意的事情。
从 Python 3.6 开始,实现这一点的最干净的方法是使用 PEP 487 中引入的 __init_subclass__
钩子。它比使用元类更简单(并且更容易管理继承)。
class Base:
@classmethod
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if 'label' not in cls.__dict__: # Check if label has been set in the class itself, i.e. not inherited from any of its superclasses
cls.label = cls.__name__ # If not, default to class's __name__
class Sub1(Base):
pass
class Sub2(Base):
label = 'Custom'
class SubSub(Sub2):
pass
print(Sub1.label) # Sub1
print(Sub2.label) # Custom
print(SubSub.label) # SubSub
我正在使用 classes 和 subclasses 的应用程序。对于每个 class,包括 super 和 sub,都有一个名为 label
的 class 变量。我希望超级 class 的 label
变量默认为 class 名称。例如:
class Super():
label = 'Super'
class Sub(Super):
label = 'Sub'
与其手动输入每个 class 的变量,是否可以从超级 class 中的 class 名称派生变量并自动填充subclasses?
class Super():
label = # Code to get class name
class Sub(Super)
pass
# When inherited Sub.label == 'Sub'.
原因是这将是默认行为。我也希望如果我可以获得默认行为,我可以稍后通过指定替代 label
.
class SecondSub(Super):
label = 'Pie' # Override the default of SecondSub.label == 'SecondSub'
我试过使用 __name__
,但它不起作用,只给了我 '__main__'
。
我想在 @classmethod
方法中使用 class 变量 label
。所以我希望能够引用该值而不必实际创建 Super() 或 Sub() 对象,如下所示:
class Super():
label = # Magic
@classmethod
def do_something_with_label(cls):
print(cls.label)
您可以 return self.__class__.__name__
在标签中作为 属性
class Super:
@property
def label(self):
return self.__class__.__name__
class Sub(Super):
pass
print Sub().label
或者您可以在 __init__
方法中设置它
def __init__(self):
self.label = self.__class__.__name__
这显然只适用于实例化的 classes
要在 class 方法中访问 class 名称,您只需在 cls
__name__
class XYZ:
@classmethod
def my_label(cls):
return cls.__name__
print XYZ.my_label()
这个解决方案也可能有效(摘自 )
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()
您可以使用 descriptor:
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'
演示:
>>> Super.label
'Super'
>>> Sub.label
'Sub'
>>> SecondSub.label
'Foo'
>>> Sub().label
'Sub'
>>> SecondSub().label
'Foo'
如果 class ThirdSub(SecondSub)
应该有 ThirdSub.label == 'ThirdSub'
而不是 ThirdSub.label == 'Foo'
,您可以多做一些工作。在 class 级别分配 label
将被继承,除非你使用元 class (这比它的价值要麻烦得多),但我们可以让 label
描述符改为查找 _label
属性:
class ClassNameDescriptor(object):
def __get__(self, obj, type_):
try:
return type_.__dict__['_label']
except KeyError:
return type_.__name__
演示:
>>> class SecondSub(Super):
... _label = 'Foo'
...
>>> class ThirdSub(SecondSub):
... pass
...
>>> SecondSub.label
'Foo'
>>> ThirdSub.label
'ThirdSub'
metaclass 在这里可能会有用。
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
免责声明:在为您的 class 提供自定义元 class 时,您需要确保它与任何 [= 使用的任何元 class(es) 兼容16=] 在其祖先中。通常,这意味着确保您的元class 继承自所有其他元class,但这样做并不容易。在实践中,metaclasses 并不常用,所以它通常只是一个 subclassing type
的问题,但这是需要注意的事情。
从 Python 3.6 开始,实现这一点的最干净的方法是使用 PEP 487 中引入的 __init_subclass__
钩子。它比使用元类更简单(并且更容易管理继承)。
class Base:
@classmethod
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if 'label' not in cls.__dict__: # Check if label has been set in the class itself, i.e. not inherited from any of its superclasses
cls.label = cls.__name__ # If not, default to class's __name__
class Sub1(Base):
pass
class Sub2(Base):
label = 'Custom'
class SubSub(Sub2):
pass
print(Sub1.label) # Sub1
print(Sub2.label) # Custom
print(SubSub.label) # SubSub