我想直接在类对象中设置一个属性,而不需要创建实例,例如:有一个可以像__ 名称 __属性一样访问的替代名称:
class Foo:
pass
> Foo.__name__
Foo
但这不起作用:
some_file.py:
class Foo:
alternativ_name = __name__ + "_ending"
print(Foo.alternativ_name)
打印:
__main___ending
如果我在交互式控制台中尝试它,它会再次返回其他内容:
>>> class Foo:
... alt_name = __name__ + "_ending"
...
>>> Foo.alt_name
'builtins_ending'
我想要达成的目标是:
class Foo:
alt_name = __name__ + "_ending"
Foo.alt_name
应该返回:
'Foo_ending'
我该怎么做?
答案 0 :(得分:1)
变量__name__
和Foo.__name__
实际上指向了两个不同的东西。在__name__
类中使用Foo
仍然使用全局变量,而不是Foo.__name__
。
在类中,不可能显式引用同一个类:
class Foo:
alt_name = Foo.__name__ + "_ending"
# raises NameError: name 'Foo' is not defined
如果您想要对象上的属性,可以在运行时执行此操作,例如在__init__
。如果你真的想要类本身的属性,你可以使用元类来实现:
class Foo:
class __metaclass__(type):
@property
def alt_name(cls):
return cls.__name__ + "_ending"
答案 1 :(得分:0)
Foo.__name__
。因此,当您访问__name__
时,它会获得模块的__name__
。有几种方法可以解决这个问题。一种是通过使用元类,但这对于仅向类添加属性来说是非常过分的。第二种是在类上使用装饰器,第三种是使alt_name
成为非数据描述符或者属性。
使用装饰者:
def add_alt_name(template):
def decorator(klass):
klass.alt_name = template.format(klass.__name__)
return klass
return decorator
@add_alt_name(template="{}_ending")
class Foo:
pass
print(Foo.alt_name)
使用非数据描述符:
class AlternativeName:
def __init__(self, template, name="alt_name"):
self.template = template
self.name = "_" + name
def __get__(self, instance, klass):
try:
return getattr(klass, self.name)
except AttributeError:
pass
alt_name = self.template.format(klass.__name__)
setattr(klass, self.name, alt_name)
return alt_name
class Foo:
alt_name = AlternativeName(template="{}_ending")
print(Foo.alt_name)
使用装饰器要简单得多。