class test(object):
def __init__(self, a = 0):
test.a = a
t = test()
print test.a ## obviously we get 0
''' ====== Question ====== '''
print test.somethingelse ## I want if attributes not exist, return None. How to do that?
First of all, you are adding the variable to the class test.a = a. You should be adding it to the instance, self.a = a. Because, when you add a value to the class, all the instances will share the data.
You can use __getattr__ function like this
class test(object):
def __init__(self, a = 0):
self.a = a
def __getattr__(self, item):
return None
t = test()
print t.a
print t.somethingelse
Quoting from the __getattr__ docs,
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self). name is the attribute name.
Note: The advantage of __getattr__ over __getattribute__ is that, __getattribute__ will be called always, we have to handle manually even if the current object has the attribute. But, __getattr__ will not be called if the attribute is found in the hierarchy.
You are looking for the __getattribute__ hook. Something like this should do what you want:
class test(object):
def __init__(self, a = 0):
self.a = a
def __getattribute__(self, attr):
try:
return object.__getattribute__(self, attr)
except AttributeError:
return None
Related
class Remote:
aa=7
def __init__(self):
self.name="Lenovo"
self.b=self.Battery()
print("this is outer",self.b.t)
class Battery:
def __init__(self):
self.name="Hp"
self.t="df"
self.c=self.Cover()
class Cover:
def __init__(self):
self.name="Arplastic"
c1=Remote()
I knew today about inner class but i don't know how to i access properties and methods of outer class into inner class please let me know anyone.
Change the constructor(s) of the inner class(es) to accept a parent argument and have the creating instance pass itself to it:
class Remote:
aa=7
def __init__(self):
self.name="Lenovo"
self.b=self.Battery(self)
print("this is outer",self.b.t)
class Battery:
def __init__(self,parent):
self.name="Hp"
self.t="df"
self.c=self.Cover(self)
self.parent=parent
class Cover:
def __init__(self,parent):
self.name="Arplastic"
self.parent=parent
c1=Remote()
print(c1.b.c.parent.parent.name) # prints 'Lenovo'
One approach is to make a metaclass that automatically creates self.parent attributes for nested classes. Note that there is a trade-off between readability and boilerplate here - many programmers would rather you just manually pass parents as arguments and add them to __init__ methods. This is more fun though, and there is something to be said for having less cluttered code.
Here is the code:
import inspect
def inner_class(cls):
cls.__is_inner_class__ = True
return cls
class NestedClass(type):
def __new__(metacls, name, bases, attrs, parent=None):
attrs = dict(attrs.items())
super_getattribute = attrs.get('__getattribute__', object.__getattribute__)
inner_class_cache = {}
def __getattribute__(self, attr):
val = super_getattribute(self, attr)
if inspect.isclass(val) and getattr(val, '__is_inner_class__', False):
if (self, val) not in inner_class_cache:
inner_class_cache[self, val] = NestedClass(val.__name__, val.__bases__, val.__dict__, parent=self)
return inner_class_cache[self, val]
else:
return val
attrs['__getattribute__'] = __getattribute__
attrs['parent'] = parent
return type(name, bases, attrs)
class Remote(metaclass=NestedClass):
aa = 7
def __init__(self):
self.name = "Lenovo"
self.b = self.Battery()
print("this is outer", self.b.t)
#inner_class
class Battery:
def __init__(self):
self.name = "Hp"
self.t = "df"
self.c = self.Cover()
#inner_class
class Cover:
def __init__(self):
self.name = "Arplastic"
print(f'{self.parent=}, {self.parent.parent=}')
c1 = Remote()
print(f'{c1.b.c.parent.parent is c1=}')
print(f'{isinstance(c1.b, c1.Battery)=}')
Output:
self.parent=<__main__.Battery object at 0x7f11e74936a0>, self.parent.parent=<__main__.Remote object at 0x7f11e7493730>
this is outer df
c1.b.c.parent.parent is c1=True
isinstance(c1.b, c1.Battery)=True
The way this works is by storing the parent as a class attribute (which is None by default), and replacing the __getattribute__ method so that all inner classes are replaced with NestedClasses with the parent attribute correctly filled in.
The inner_class decorator is used to mark a class as an inner class by setting the __is_inner_class__ attribute.
def inner_class(cls):
cls.__is_inner_class__ = True
return cls
This is not strictly necessary if all attributes that are classes should be treated as inner classes, but it's good practice to do something like this to prevent Bar.foo being treated as an inner class in this example:
class Foo:
pass
class Bar(metaclass=NestedClass):
foo = Foo
All the NestedClass metaclass does is take the description of the class and modify it, adding the parent attribute:
class NestedClass(type):
def __new__(metacls, name, bases, attrs, parent=None):
attrs = dict(attrs.items())
...
attrs['parent'] = parent
return type(name, bases, attrs)
...and modifying the __getattribute__ method. The __getattribute__ method is a special method that gets called every time an attribute is accessed. For example:
class Foo:
def __init__(self):
self.bar = "baz"
def __getattribute__(self, item):
return 1
foo = Foo()
# these assert statements pass because even though `foo.bar` is set to "baz" and `foo.remote` doesn't exist, accessing either of them is the same as calling `Foo.__getattribute(foo, ...)`
assert foo.bar == 1
assert foo.remote == 1
So, by modifying the __getattribute__ method, you can make accessing self.Battery return a class that has its parent attribute equal to self, and also make it into a nested class:
class NestedClass(type):
def __new__(metacls, name, bases, attrs, parent=None):
attrs = dict(attrs.items())
# get the previous __getattribute__ in case it was not the default one
super_getattribute = attrs.get('__getattribute__', object.__getattribute__)
inner_class_cache = {}
def __getattribute__(self, attr):
# get the attribute
val = super_getattribute(self, attr)
if inspect.isclass(val) and getattr(val, '__is_inner_class__', False):
# if it is an inner class, then make a new version of it using the NestedClass metaclass, setting the parent attribute
if (self, val) not in inner_class_cache:
inner_class_cache[self, val] = NestedClass(val.__name__, val.__bases__, val.__dict__, parent=self)
return inner_class_cache[self, val]
else:
return val
attrs['__getattribute__'] = __getattribute__
attrs['parent'] = parent
return type(name, bases, attrs)
Note that a cache is used to ensure that self.Battery will always return the same object every time rather than re-making the class every time it is called. This ensures that checks like isinstance(c1.b, c1.Battery) work correctly, since otherwise c1.Battery would return a different object to the one used to create c1.b, causing this to return False, when it should return True.
And that's it! You can now enjoy nested classes without boilerplate!
The first code snippet:
class A:
def __init__(self):
print(self.__dict__)
def __getattr__(self, name):
print("get")
def __setattr__(self, name, value):
print("set")
# def __getattribute__(self, name):
# print("getatrr")
a = A()
It prints {} and the function __getattr__ isn't invoked, which means the attribute__dict__ exists.
The second snippet:
class A:
def __init__(self):
print(self.__dict__)
def __getattr__(self, name):
print("get")
def __setattr__(self, name, value):
print("set")
def __getattribute__(self, name):
print("getatrr")
a = A()
It prints getatrr and None, which means the attribute __dict__ doesn't exist.
Why is __dict__ {} in the first case, but None in the second case?
the issue is that when you define this:
def __getattribute__(self, name):
print("getatrr")
you're overriding __getattribute__ which is supposed to return something. Since you're not returning anything, you get None for every attribute you'll try.
Documentation states:
This method should return the (computed) attribute value or raise an AttributeError exception
A viable way to define it is to call object.__getattribute__ in the fallback case (in my example, I have added a small test on __dict__ which prints:
def __getattribute__(self, name):
if name == "__dict__":
print("get attribute invoked with __dict__")
return object.__getattribute__(self,name)
In the end, the hard attribute lookup work is done with object.__getattribute__ that invokes python runtime.
Does Python have a mechanism for class constructors, i.e. a function that is called whenever the class is first referenced (as opposed to when an instance of that object is created)? I know this exists in some other languages, but I haven't come across it in Python.
Basically, I would like to initialise some static attributes in that function. I put an example below of what I would expect. Of course, the example returns None, but I would like it return 'foo'.
class T:
arg = None
def __class_constructor__():
T.arg = 'foo'
print(T.arg) # returns None
To avoid confusion: I am well aware of the object constructor, but that's not what I want, because it is only called once the first object is created, not before:
class T:
arg = None
def __init__(self):
type(self).arg = 'foo'
print(T.arg) # returns None
obj = T()
print(T.arg) # returns 'foo'
You can use a class decorator:
def add_arg(cls):
if not hasattr(cls, "arg"):
cls.arg = 'foo'
return cls
#add_arg
class T(object):
pass
Or a custom metaclass:
class WithArg(type):
def __new__(meta, name, bases, attrs):
cls = type.__new__(meta, name, bases, attrs)
if not hasattr(cls, "arg"):
cls.arg = "foo"
return cls
# python 2
class T(object):
__metaclass__ = WithArg
# python 3
class T(metaclass=WithArg):
pass
But as others already mention this won't give you much more than plainly setting the class attribute in the class statement.
NB : if you want a computed attribute on the class itself, you'll have to either set it as a property on a custom metaclass
class WithProp(type):
#property
def arg(cls):
return "foo"
class T(object):
__metaclass__ = WithProp
T.arg
=> 'foo'
But arg will only be available on the class object itself, not on it's instances:
T().arg
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'T' object has no attribute 'arg'
or write your own custom descriptor:
class ArgDescriptor(object):
def __get__(self, obj, cls=None):
return 42
class T(object):
arg = ArgDescriptor()
T.arg
=> 42
T().arg
=> 42
You simply have to initialise the class variable when declaring it within the class
class T:
arg = 'foo' #this initialises the class instance
def __init__(self):
self.arg = 'bar' #this initialises the object instance
print(T.arg) # class instance returns 'foo'
obj = T()
print(T.arg) # class instance still returns 'foo'
print(obj.arg) # object instance returns 'bar'
I create a static_init decorator which calls a static_init class method if it exists. This static_init class method will run when the class decorator is evaluated which is when the class is defined - so not quite when the class is first referenced - but it is analogous to static initialization in other languages like Java.
Here is the decorator and example of how to use it to initialize a class variable on an enum class:
# pylint: disable=missing-docstring,no-member
import enum
def static_init(cls):
if getattr(cls, "static_init", None):
cls.static_init()
return cls
#static_init
class SomeEnum(enum.Enum):
VAL_A = enum.auto()
VAL_B = enum.auto()
VAL_C = enum.auto()
VAL_D = enum.auto()
#classmethod
def static_init(cls):
text_dict = {}
setattr(cls, 'text_dict', text_dict)
for value in cls:
text_dict[value.name.lower().replace("_", " ").title()] = value
def test_static_init():
assert SomeEnum.text_dict["Val A"] == SomeEnum.VAL_A
assert SomeEnum.text_dict["Val B"] == SomeEnum.VAL_B
assert SomeEnum.text_dict["Val C"] == SomeEnum.VAL_C
assert SomeEnum.text_dict["Val D"] == SomeEnum.VAL_D
I have a class in which a method first needs to verify that an attribute is present and otherwise call a function to compute it. Then, ensuring that the attribute is not None, it performs some operations with it. I can see two slightly different design choices:
class myclass():
def __init__(self):
self.attr = None
def compute_attribute(self):
self.attr = 1
def print_attribute(self):
if self.attr is None:
self.compute_attribute()
print self.attr
And
class myclass2():
def __init__(self):
pass
def compute_attribute(self):
self.attr = 1
return self.attr
def print_attribute(self):
try:
attr = self.attr
except AttributeError:
attr = self.compute_attribute()
if attr is not None:
print attr
In the first design, I need to make sure that all the class attributes are set to None in advance, which can become verbose but also clarify the structure of the object.
The second choice seems to be the more widely used one. However, for my purposes (scientific computing related to information theory) using try except blocks everywhere can be a bit of an overkill given that this class doesn't really interact with other classes, it just takes data and computes a bunch of things.
Firstly, you can use hasattr to check if an object has an attribute, it returns True if the attribute exists.
hasattr(object, attribute) # will return True if the object has the attribute
Secondly, You can customise attribute access in Python, you can read more about it here: https://docs.python.org/2/reference/datamodel.html#customizing-attribute-access
Basically, you override the __getattr__ method to achieve this, so something like:
class myclass2():
def init(self):
pass
def compute_attr(self):
self.attr = 1
return self.attr
def print_attribute(self):
print self.attr
def __getattr__(self, name):
if hasattr(self, name) and getattr(self, name)!=None:
return getattr(self, name):
else:
compute_method="compute_"+name;
if hasattr(self, compute_method):
return getattr(self, compute_method)()
Make sure you only use getattr to access the attribute within __getattr__ or you'll end up with infinite recursion
Based on the answer jonrsharpe linked, I offer a third design choice. The idea here is that no special conditional logic is required at all either by the clients of MyClass or by code within MyClass itself. Instead, a decorator is applied to a function that does the (hypothetically expensive) computation of the property, and then that result is stored.
This means that the expensive computation is done lazily (only if a client tries to access the property) and only performed once.
def lazyprop(fn):
attr_name = '_lazy_' + fn.__name__
#property
def _lazyprop(self):
if not hasattr(self, attr_name):
setattr(self, attr_name, fn(self))
return getattr(self, attr_name)
return _lazyprop
class MyClass(object):
#lazyprop
def attr(self):
print('Generating attr')
return 1
def __repr__(self):
return str(self.attr)
if __name__ == '__main__':
o = MyClass()
print(o.__dict__, end='\n\n')
print(o, end='\n\n')
print(o.__dict__, end='\n\n')
print(o)
Output
{}
Generating attr
1
{'_lazy_attr': 1}
1
Edit
Application of Cyclone's answer to OP's context:
class lazy_property(object):
'''
meant to be used for lazy evaluation of an object attribute.
property should represent non-mutable data, as it replaces itself.
'''
def __init__(self, fget):
self.fget = fget
self.func_name = fget.__name__
def __get__(self, obj, cls):
if obj is None:
return None
value = self.fget(obj)
setattr(obj, self.func_name, value)
return value
class MyClass(object):
#lazy_property
def attr(self):
print('Generating attr')
return 1
def __repr__(self):
return str(self.attr)
if __name__ == '__main__':
o = MyClass()
print(o.__dict__, end='\n\n')
print(o, end='\n\n')
print(o.__dict__, end='\n\n')
print(o)
The output is identical to above.
Is there any universal way to get the attributes of a class by class name and instance?
class A:
def __init__(self):
self.prop = 1
a = A()
for attr, value in a.__dict__.items():
print(attr, value) # prop, 1
.
class A:
def __init__(self):
self.prop = 1
for attr, value in A.__dict__.items():
print(attr, value)
#__dict__, __doc__, __init__, __module__, __weakref__
Why the last example returns dir attibutes why the results differ?
__dict__, __doc__, __module__, ... are actually present in a class, even you haven't created them. They are 'built-in'.
So it's normal that dir shows them to you.
__dict__ attribute in an instance stores instance attributes.
class A:
def __init__(self):
self.prop = 1
a = A()
for attr, value in a.__dict__.items():
print(attr, value)
This shows instance attributes. And there is just one instance attribute - prop (self.prop = 1)
for attr, value in A.__dict__.items():
And this gets class attributes. prop was added to an instance, so it's not here.
See http://docs.python.org/library/stdtypes.html#special-attributes
To get from an object all attributes, including class attributes, base class attributes, use inspect.getmembers