Unfortunately, in Python, a class attribute cannot reference its class name. The following raises a NameError
:
class Foo(object):
bar = Foo
In a situation where a class attribute must reference its class name (in my case, it's part of a validation scheme for a library). What is the clearest way to do so?
The following is my current attempt:
class Foo(object):
bar = None
Foo.bar = Foo
This works, but even with comments is likely to cause confusion, since you expect a class attribute to be initialized when declared, not after the class is declared.
Does anyone have a better workaround?
A class attribute is shared by all instances of the class. To define a class attribute, you place it outside of the __init__() method. Use class_name. class_attribute or object_name.
Accessing the attributes of a classgetattr() − A python method used to access the attribute of a class. hasattr() − A python method used to verify the presence of an attribute in a class. setattr() − A python method used to set an additional attribute in a class.
Class attributes are the variables defined directly in the class that are shared by all objects of the class. Instance attributes are attributes or properties attached to an instance of a class. Instance attributes are defined in the constructor. Defined directly inside a class.
Any variable that is bound in a class is a class attribute . Any function defined within a class is a method . Methods receive an instance of the class, conventionally called self , as the first argument.
Class attributes are useful in some cases such as storing class constants, tracking data across all instances, and defining default values. Since a constant doesn’t change from instance to instance of a class, it’s handy to store it as a class attribute.
When to use Python class attributes 1 Storing class constants#N#Since a constant doesn’t change from instance to instance of a class, it’s handy to store it... 2 Tracking data across of all instances More ...
When you try to access an attribute from an instance of a class, it first looks at its instance namespace. If it finds the attribute, it returns the associated value. If not, it then looks in the class namespace and returns the attribute (if it’s present, throwing an error otherwise). For example:
The Test class has two attributes with the same name ( x) one is the instance attribute and the other is a class attribute. When we access the x attribute via the instance of the Test class, it returns 20 which is the variable of the instance attribute.
Use a meta class to automatically set it.
def my_meta(name, bases, attrs):
cls = type(name, bases, attrs)
cls.bar = cls
return cls
class Foo(object):
__metaclass__ = my_meta
>>> print Foo.bar
<class '__main__.Foo'>
You could define a class decorator that replaced placeholder strings with the class being defined:
def fixup(cls):
placeholder = '@' + cls.__name__
for k,v in vars(cls).items():
if v == placeholder:
setattr(cls, k, cls)
return cls
@fixup
class Foo(object):
bar = '@Foo'
print('Foo.bar: {!r}'.format(Foo.bar)) # -> Foo.bar: <class '__main__.Foo'>
Another alternative would be to use the __init_subclass__()
special method which was introduced in Python 3.6 to create a base class and then derive your class from it instead of the generic object
:
class Base(object):
def __init_subclass__(cls, /, **kwargs):
super().__init_subclass__(**kwargs)
cls.bar = cls
class Foo(Base):
pass
print('Foo.bar: {!r}'.format(Foo.bar)) # -> Foo.bar: <class '__main__.Foo'>
You can use a class decorator
def moi(fieldname):
def _selfref(cls):
setattr(cls, fieldname, cls.__name__)
return cls
return _selfref
usage:
@moi('bar')
class Foo(object):
pass
then:
>>> print Foo.bar
Foo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With