Why object's attributes are not there when the class is instantiated? - python

Why instantiating a class does not instantiate all its attributes ? I think a very simple example could explain my problem better:
class Example:
def example(self):
self.var=10
if __name__=='__main__':
E=Example()
# In this case, the attribute var is not instantiated
try:
attr=getattr(E,"var")
print(attr) # <-- it does not exist even if E instantiated Example class
except AttributeError:
print("Object not having this attribute") # <-- This is the output
Why the object E does not have all its attributes instantiated (namely the attribute var) ?

Unlike Java, in Python, the initiator function is called __init__; naming the method like the name of the class does not create a constructor.
So, when you instantiate an object of class Example, the method example is not called and your attribute doesn't exist. You'll have to call it explicitly, like this:
>>> e = Example()
>>> e.example()
>>> e.var
10
To have the attribute available to all objects at instantiation, modify your class and create a __init__ method, like this:
class Example:
def __init__(self):
self.var = 10
Now, it will work as you expect:
>>> e = Example()
>>> e.var
10

in your class if you need to initialize var you need to call it explicitly by calling the example method in the example class
but if if you write __init__ method it it automatically initialize the variable at the time of object creation
The init method (init for initialise) is called when the object is instantiated. Instantiation is done by (effectively) calling the
class.Here a new instance is created. Then its init method is called .it call the example method to initialize var in the exapme
class Example:
def __init__(self):
self.var=0 # or you can directly give self.var=10
self.example()
def example(self):
self.var=10
if __name__=='__main__':
E=Example()
# In this case, the attribute var is not instantiated
try:
attr=getattr(E,"var")
print(attr) # <-- it does not exist even if E instantiated Example class
except AttributeError:
print("Object not having this attribute")
other way of doing is
when you intalized class object call the method in it
E=Example()
E.example()#explicitly call example method in the class

You not called example method which sets var to self.
try
if __name__=='__main__':
E=Example()
E.example()
# In this case, the attribute var is not instantiated
try:
attr=getattr(E,"var")
print(attr)
except AttributeError:
print("Object not having this attribute")

Related

Syntax confusion during calling of functions from python classes [duplicate]

This question already has answers here:
python class instance variables and class variables
(4 answers)
Closed 4 years ago.
Sorry this is my first time asking a question, my formatting may be wrong. I am unsure about the syntax for calling functions from a class without creating an instance of the class. For the code:
class A_Class:
var = 10
def __init__(self):
self.num = 12
def print_12(self):
return 12
How come I am able to call
print(A_Class.var)
And have the console print out the value 10, but if I were to call
print(A_Class.num)
Then I get the error:
AttributeError: type object 'A_Class' has no attribute 'num'
And if I try to call
print(A_Class.print_12)
Then the console prints:
<function A_Class.print_12 at 0x039966F0>
And not the value 12
I am confused with how to call functions from classes.
var is a Class variable, while num is an instance variable, as an example:
class A_Class:
var = 10
def __init__(self):
self.num = 12
def print_12(self):
return 12
a = A_Class()
As a class variable, it belongs to the class and you are able to call it.
print(A_Class.var)
>> 10
As an instance variable, you have to instantiate it before you can access the values, this is why self (self has no special meaning and can be anything, but always the first argument for instance methods) is used and is initialized in the special __init__ method.
a = A_Class()
print(a.num)
>> 12
Finally, you want to print the returned value, and therefore will have to call it such as:
var = a.print_12()
print(var)
>> 12
As you were missing the parenthesis earlier, it is the instance method itself, and therefore did not return any value.
To expand on #BernardL excellent answer about the differences between a class variable and an instance variable, I wish to add this is from the PyTricks newsletter I get which may help answer your question about print(A_Class.print_12).
# #classmethod vs #staticmethod vs "plain" methods
# What's the difference?
class MyClass:
def method(self):
"""
Instance methods need a class instance and
can access the instance through `self`.
"""
return 'instance method called', self
#classmethod
def classmethod(cls):
"""
Class methods don't need a class instance.
They can't access the instance (self) but
they have access to the class itself via `cls`.
"""
return 'class method called', cls
#staticmethod
def staticmethod():
"""
Static methods don't have access to `cls` or `self`.
They work like regular functions but belong to
the class's namespace.
"""
return 'static method called'
# All methods types can be
# called on a class instance:
>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x1019381b8>)
>>> obj.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)
>>> obj.staticmethod()
'static method called'
# Calling instance methods fails
# if we only have the class object:
>>> MyClass.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)
>>> MyClass.staticmethod()
'static method called'
>>> MyClass.method()
TypeError:
"unbound method method() must be called with MyClass "
"instance as first argument (got nothing instead)"
This is because what you define in the class root level is a static variable or method.
Also the methods within the class are objects themselfs, so if you print them this returns the object type and memory address as there is not way defined to print (or convert to string) the object (normally specified with __str__ otherwise).

Set attribute on class but not on instances

I'm creating some custom classes in Python and I was wondering if there was any way to define an attribute on a class without having all of its instances inherit the attribute.
For example:
class Foo():
def bar():
pass
Foo.bar # would return `bar` function
instanceOfFoo = Foo()
instanceOfFoo.bar # would raise an AttributeError
I know I could subclass Foo, override bar, and manually raise an AttributeError as a #property to give the "appearance" that bar doesn't exist, but is there any way to do this without subclasses?
Context: I'm trying to replicate the Date class from JavaScript, where calling Date.parse (on the Date class itself) will do something, but calling parse on a Date instance will not do anything because instances don't inherit the parse function from Date. (They inherit all their properties from Date.prototype which is why it works there.)
I found what I was looking for using metaclasses.
class MetaFoo(type):
def bar(self):
pass
class Foo(metaclasses=MetaFoo):
pass
Foo.bar # returns `bar` method
instanceOfFoo = Foo()
instanceOfFoo.bar # raises AttributeError
Foo is being created using the MetaFoo class and is inheriting the bar method in the process. Since inheritance only works with direct instances of a class, Foo (an instance of MetaFoo) inherits the bar method, but instanceOfFoo (an instance of Foo but not MetaFoo) does not inherit the method.
There is one work-around for your question. Note that in python You can't call Foo.bar(), unless bar() is declared either as #staticmethod or #classmethod.
class Foo(object):
def __init__(self):
self.bar = self.foo
#classmethod
def bar(cls):
return 1
#classmethod
def foo(cls):
raise AttributeError("Method not implemented for instances of a class.")
print(Foo.bar()) # --> 1
t = Foo()
print(t.bar()) # --> AttributeError: Method not implemented for instances of a class.

Initialize object properties as class properties first in Python

I have the habit to initialize the properties of an instance of a class in the constructor of that class but, in case the properties are very tight to the class, I also declare them and initialize them to None ([] or some other base value) as properties in the class.
For instance:
class AClass(object):
aprop = None
def __init__(self):
self.aprop = "avalue"
Which in most of the cases it won't make much of a difference from just doing:
class AClass(object):
def __init__(self):
self.aprop = "avalue"
However, if somebody gets the scope of the AClass will notice that an instance of this class is expected to have an attribute named aprop. I think of it as a placeholder for the property aprop in the class.
This looks to me more as a question of style, but I would like to know whether this is a good practice. Would you recommend it? Is it something common? or should I try to get rid of it?
When you do self.aprop = "avalue" in the __init__ function, every instance of AClass will have the aprop property since __init__ is called when you initiate an instance. This makes aprop an instance variable.
When you do aprop = None you add a class variable to AClass. This means that the class itself will have this property.
For Example:
>>> class AClass(object):
... def __init__(self):
... self.aprop = "avalue"
...
>>> AClass.aprop
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'AClass' has no attribute 'aprop'
And:
>>> class AClass(object):
... aprop = None
... def __init__(self):
... self.aprop = "avalue"
...
>>> AClass.aprop
>>> print AClass.aprop
None
So if you want your class to have this property you should define it as a class variable. If you only use it in instances, the only case you should define a class property is if you don't always redefine it (hide it) in __init__:
class AClass(object):
aprop = None
def __init__(self):
self.bprop = "bvalue"
Unless you ever access the property on the class itself (e.g. as AClass.aprop) rather than on an instance, there's no need to make it a class member if you always populate it on an instance in the __init__ method.
My vote is to always write the least amount of code necessary to clearly convey the intent. Adding an extra member to the class obscures the intent (since your actual goal here is for it to be an instance property) and is unnecessary: that sounds like two strikes against it.

When setting data fields in Python objects, should I use the "self" keyword?

Should I write
class MyClass:
def __init__(self):
self.field = 0
or
class MyClass:
def __init__(self):
field = 0
Is there any difference between these statements?
Yes, you must use the self variable to set the properties of Python objects/instances.
In the second case, you're just creating a local variable in __init__, not defining a property.
class MyClass:
def __init__(self):
field = 0
print MyClass().field # an error! it's not defined!
You may be misled by the way that you can just use raw assignments in class blocks to set class properties:
class MyClass:
a = 2
print MyClass.a # 2
The behaviour in class blocks is unusual, and you don't get similar behaviour inside methods.
The first chunk of code creates an instance attribute that can be accessed once an instance of the class has been created:
>>> a = MyClass()
>>> a.field
0
The scope of the second chunk's field variable is only within the __init__ function, so accessing the variable outside of that scope won't work:
>>> a = MyClass()
>>> a.field
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute 'field'
The former sets the value as a property of the class. The latter, as simply a local variable.
If elsewhere in your program you do
foo = MyClass();
print foo.field;
The print statement above will only work with the first code snippet, not with the second.

How do I set and access attributes of a class? [duplicate]

This question already has answers here:
How can I access "static" class variables within methods?
(6 answers)
Closed 12 days ago.
Suppose I have this code:
class Example(object):
def the_example(self):
itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
When I try it, I get an error that says:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Example' object has no attribute 'itsProblem'
How do I access this attribute? I tried adding another method to return it:
def return_itsProblem(self):
return itsProblem
but the problem persists.
The answer, in a few words
In your example, itsProblem is a local variable.
Your must use self to set and get instance variables. You can set it in the __init__ method. Then your code would be:
class Example(object):
def __init__(self):
self.itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
But if you want a true class variable, then use the class name directly:
class Example(object):
itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
But be careful with this one, as theExample.itsProblem is automatically set to be equal to Example.itsProblem, but is not the same variable at all and can be changed independently.
Some explanations
In Python, variables can be created dynamically. Therefore, you can do the following:
class Example(object):
pass
Example.itsProblem = "problem"
e = Example()
e.itsSecondProblem = "problem"
print Example.itsProblem == e.itsSecondProblem
prints
True
Therefore, that's exactly what you do with the previous examples.
Indeed, in Python we use self as this, but it's a bit more than that. self is the the first argument to any object method because the first argument is always the object reference. This is automatic, whether you call it self or not.
Which means you can do:
class Example(object):
def __init__(self):
self.itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
or:
class Example(object):
def __init__(my_super_self):
my_super_self.itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
It's exactly the same. The first argument of ANY object method is the current object, we only call it self as a convention. And you add just a variable to this object, the same way you would do it from outside.
Now, about the class variables.
When you do:
class Example(object):
itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
You'll notice we first set a class variable, then we access an object (instance) variable. We never set this object variable but it works, how is that possible?
Well, Python tries to get first the object variable, but if it can't find it, will give you the class variable. Warning: the class variable is shared among instances, and the object variable is not.
As a conclusion, never use class variables to set default values to object variables. Use __init__ for that.
Eventually, you will learn that Python classes are instances and therefore objects themselves, which gives new insight to understanding the above. Come back and read this again later, once you realize that.
You are declaring a local variable, not a class variable. To set an instance variable (attribute), use
class Example(object):
def the_example(self):
self.itsProblem = "problem" # <-- remember the 'self.'
theExample = Example()
theExample.the_example()
print(theExample.itsProblem)
To set a class variable (a.k.a. static member), use
class Example(object):
def the_example(self):
Example.itsProblem = "problem"
# or, type(self).itsProblem = "problem"
# depending what you want to do when the class is derived.
If you have an instance function (i.e. one that gets passed self) you can use self to get a reference to the class using self.__class__
For example in the code below tornado creates an instance to handle get requests, but we can get hold of the get_handler class and use it to hold a riak client so we do not need to create one for every request.
import tornado.web
import riak
class get_handler(tornado.web.requestHandler):
riak_client = None
def post(self):
cls = self.__class__
if cls.riak_client is None:
cls.riak_client = riak.RiakClient(pb_port=8087, protocol='pbc')
# Additional code to send response to the request ...
Implement the return statement like the example below! You should be good. I hope it helps someone..
class Example(object):
def the_example(self):
itsProblem = "problem"
return itsProblem
theExample = Example()
print theExample.the_example()
If you have a #classmethod static method, you always have the class as the first parameter:
class Example(object):
itsProblem = "problem"
#classmethod
def printProblem(cls):
print(cls.itsProblem)
Example.printProblem()

Categories

Resources