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).
Related
I am python Begineer and i learned that first parameter inside the method should be contain some 'self' keyword but i found the following program runs without self keyword can you explain about this below is my code...
class Student(object):
def __init__(self,name,age):
self.name = name
self.age = age
def get_biggest_number(*age):
result=0
for item in age:
if item > result:
result= item
return result
Sam = Student("Sam",18)
Peter = Student("Peter",20)
Karen = Student("Karen",22)
Mike = Student("Michael",21)
oldest= Student.get_biggest_number(Sam.age,Peter.age,Karen.age,Mike.age)
print (f"The oldest student is {oldest} years old.")
Code you've posted has indentation errors within it, you should first indent methods and it's content, meaning that, methods are within class. On the other hand, self refers to instance, which calls specific method and gives access to the all instance data. For example
student1 = Student('name1', 20)
student2 = Student('name2', 21)
student1.some_method(arg1)
in the last call, behind the scenes student1 is passed for self parameter of the method, meaning that all student1's data is available through self argument.
What you are trying is to use staticmethod, which has no data of the instance and is aimed to logically group class related functions without explicit instance, which does not require self in method definition:
class Student:
...
#staticmethod
def get_biggest_number(*ages):
# do the task here
On the other hand, if you would like to track all student instances and apply get_biggest_number method automatically work on them, you just have to define class variable (rather than instance variable) and on each instance __init__ append new instance to that list:
class Student:
instances = list() # class variable
def __init__(self, name, age):
# do the task
Student.instances.append(self) # in this case self is the newly created instance
and in get_biggest_number method you just loop through Student.instances list which will contain Student instance and you can access instance.age instance variable:
#staticmethod
def get_biggest_number():
for student_instance in Student.instances:
student_instance.age # will give you age of the instance
Hope this helps.
You shouldn't mistake classmethod with instance methods.
In python you can declare a method inside a class as classmethod.
This method takes a reference to the class as the first argument.
class Student(object):
def __init__(self,name,age):
self.name = name
self.age = age
def get_biggest_number(self, *age):
result=0
for item in age:
if item > result:
result= item
return result
#classmethod
def get_classname(cls):
# Has only access to class bound items
# gets the class as argument to access the class
return cls.__name__
#staticmethod
def print_foo():
# has not a reference to class or instance
print('foo')
self in python refers to the instance of the class that is created. Something like this in C# and Java. However there's some differences but in short: when you don't use self as input of a method, actually you're saying that this method does not need any instance, that means this method is a static method and will never use any of class attributes.
In your example we can call get_biggest_number method with not even one instance, for example you can call this method just like this:
Student.get_biggest_number(20,30,43,32)
and the output will be 43.
The self keyword is used to represent an instance (object) of the given class. ... However, since the class is just a blueprint, self allows access to the attributes and methods of each object in python.
class ClassA:
def methodA(self, arg1, arg2):
self.arg1 = arg1
self.arg2 = arg2
let say ObjectA is an instance of the class.
Now when ObjectA.methodA(arg1, arg2) is called, python internally converts it as:
ClassA.methodA(ObjectA, arg1, arg2)
The self variable refers to the object itself and the code becomes as:
class ClassA:
def methodA(ObjectA, arg1, arg2):
ObjectA.arg1 = arg1
ObjectA.arg2 = arg2
I'm reading Fluent Python chapter 19 > A Proper Look at Properties, and I'm confused about the following words:
Properties are always class attributes, but they actually manage attribute access in the instances of the class.
The example code is:
class LineItem:
def __init__(self, description, weight, price):
self.description = description
self.weight = weight # <1>
self.price = price
def subtotal(self):
return self.weight * self.price
#property # <2>
def weight(self): # <3>
return self.__weight # <4>
#weight.setter # <5>
def weight(self, value):
if value > 0:
self.__weight = value # <6>
else:
raise ValueError('value must be > 0') # <7>
From my previous experiences, class attributes are belong to the class itself and shared by all the instances. But here, weight, the property, is an instance method and the value returned by it is different between instances. How is it eligible to be a class attribute? Doesn't it that all the class attributes should be the same for any instances?
I think I misunderstand something, so I hope to get a correct explanation. Thanks!
A distinction is made because when you define a #property on a class, that property object becomes an attribute on the class. Whereas when you define attributes against an instance of your class (in your __init__ method), that attribute only exists against that object. This might be confusing if you do:
>>> dir(LineItem)
['__class__', ..., '__weakref__', 'subtotal', 'weight']
>>> item = LineItem("an item", 3, 1.12)
>>> dir(item)
['__class__', ..., '__weakref__', 'description', 'price', 'subtotal', 'weight']
Notice how both subtotal and weight exist as attributes on your class.
I think it's also worth noting that when you define a class, code under that class is executed. This includes defining variables (which then become class attributes), defining functions, and anything else.
>>> import requests
>>> class KindOfJustANamespace:
... text = requests.get("https://example.com").text
... while True:
... break
... for x in range(2):
... print(x)
...
0
1
>>> KindOfJustANamespace.text
'<!doctype html>\n<html>\n<head>\n <title>Example Domain...'
A #decorator is just "syntactic sugar". Meaning #property over a function if the same as function = property(function). This applies to functions defined inside a class as well, but now the function is part of the class's namespace.
class TestClass:
#property
def foo(self):
return "foo"
# ^ is the same as:
def bar(self):
return "bar"
bar = property(bar)
A good explanation of property in Python can be found here: https://stackoverflow.com/a/17330273/7220776
From my previous experiences, class attributes are belong to the class itself and shared by all the instances.
That's right.
But here, weight, the property, is an instance method
No, it's a property object. When you do:
#decorator
def func():
return 42
it's actually syntactic sugar for
def func():
return 42
func = decorator(func)
IOW the def statement is executed, the function object created, but instead of beeing bound to it's name, it's passed to the decorator callable, and the name is bound to whatever decorator() returned.
In this case the decorator is the property class itself, so the weight attribute is a property instance. You can check this out by yourself by inspecting LineItem.weight (which will return the property object itself).
and the value returned by it is different between instances.
Well yes of course, how is this surprising ? LineItem.subtotal is a class attribute also (like all methods), yet it returns values from the instance it's called on (which is passed to the function as the self param).
How is it eligible to be a class attribute? Doesn't it that all the class attributes should be the same for any instances?
The class attributes ARE the same for all instances of a class, yes. There's only one single subtotal function for all instances of LineItem.
A property is mainly a shortcut to make a function (or a pair of functions if you specify a setter) look like it's a plain attribute, so when you type mylinitem.weight, what is really executed is LineItem.weight.fget(mylineitem), where fget is the getter function you decorated with #property. The mechanism behind this is known as the "descriptor protocol", which is also used to turn mylineitem.subtotal() into LineItem.subtotal(mylineitem) (python functions implement the descriptor protocol to return "method" objects, which are themselves wrappers around the function and the current instance and insert the instance as first argument to the function call).
So it's not suprising that properties are class attributes - you only need one property instance to "serve" all instances of the class -, and moreover, properties - like all descriptors FWIW - MUST actually be class attributes to work as expected, since the descriptor protocol is only invoked on class attributes (there's no use case for a "per instance" computed attribute since the function in charge of the "computation" will get the instance as parameter).
I finally understand the descriptor and property concept through Simeon Franklin's excellent presentation, the following contents can be seen as a summary on his lecture notes. Thanks to him!
To understand properties, you first need to understand descriptors, because a property is implemented by a descriptor and python's decorator syntactic sugar. Don't worry, it's not that difficult.
What is a descriptor:
a descriptor is any object that implements at least one of methods named __get__(), __set__(), and __delete__().
Descriptor can be divided into two categories:
A data descriptor implements both __get__() and __set__().
A non-data descriptor implements only __get__().
According to python's HowTo:
a descriptor is an object attribute with “binding behavior”, one whose attribute access has been overridden by methods in the descriptor protocol.
Then what is the descriptor protocol? Basically speaking, it's just says that when Python interpreter comes across an attribute access like obj.attr,it will search in some order to resolve this .attr , and if this attr is a descriptor attribute, then this descriptor will take some precedence in this specific order and this attribute access will be translated into a method call on this descriptor according to the descriptor protocol, possibly shadowing a namesake instance attribute or class attribute. More concretely, if attr is a data descriptor, then obj.attr will be translated into the calling result of this descriptor's __get__ method; if attr is not a data descriptor and is an instance attribute, this instance attribute will be matched; if attr is not in above, and it is a non-data descriptor, we get the calling result of this non-data descriptor's __get__ method. Full rules on attribute resolution can be found here .
Now let's talk about property. If you have looked at Python' descriptor HowTo, you can find a pure Python version implementation of property:
class Property(object):
"Emulate PyProperty_Type() in Objects/descrobject.c"
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
if doc is None and fget is not None:
doc = fget.__doc__
self.__doc__ = doc
def __get__(self, obj, objtype=None):
if obj is None:
return self
if self.fget is None:
raise AttributeError("unreadable attribute")
return self.fget(obj)
def __set__(self, obj, value):
if self.fset is None:
raise AttributeError("can't set attribute")
self.fset(obj, value)
def __delete__(self, obj):
if self.fdel is None:
raise AttributeError("can't delete attribute")
self.fdel(obj)
def getter(self, fget):
return type(self)(fget, self.fset, self.fdel, self.__doc__)
def setter(self, fset):
return type(self)(self.fget, fset, self.fdel, self.__doc__)
def deleter(self, fdel):
return type(self)(self.fget, self.fset, fdel, self.__doc__)
Apparently,property is a data descriptor!
#property just uses python's decorator syntactic sugar.
#property
def attr(self):
pass
is equivalent to:
attr = property(attr)
So, attr is no longer an instance method as I posted in thie question, but is translated into a class attribute by the decorator syntactic sugar as the author said. It's a descriptor object attribute.
How is it eligible to be a class attribute?
OK, we solved it now.
Then:
Doesn't it that all the class attributes should be the same for any instances?
No!
I steal an example from Simeon Franklin's excellent presentation .
>>> class MyDescriptor(object):
... def __get__(self, obj, type):
... print self, obj, type
... def __set__(self, obj, val):
... print "Got %s" % val
...
>>> class MyClass(object):
... x = MyDescriptor() # Attached at class definition time!
...
>>> obj = MyClass()
>>> obj.x # a function call is hiding here
<...MyDescriptor object ...> <....MyClass object ...> <class '__main__.MyClass'>
>>>
>>> MyClass.x # and here!
<...MyDescriptor object ...> None <class '__main__.MyClass'>
>>>
>>> obj.x = 4 # and here
Got 4
Pay attention to obj.x and its output. The second element in its output is <....MyClass object ...> . It's the specific instance obj . Shortly speaking, because this attribute access has been translated into a __get__ method call, and this __get__ method get the specific instance argument as its method signature descr.__get__(self, obj, type=None) demands, it can return different values according to which instance it is been called by.
Note: my English explanation maybe not clear enough, so I highly recommend you to look at Simeon Franklin's notes and Python's descriptor HowTo.
You didn't misunderstand. Don't worry, just read on. It will become clear in the next chapter.
The same book explains in chapter 20 that they can be a class attributes because of the descriptor protocol. The documentation explains how properties are implemented as descriptors.
As you see from the example, properties are really class attributes (methods). When called, they get a reference to the instance, and writes/reads to its underlying __dict__.
I think the example is wrong, the init shoul look like this:
def __init__(self, description, weight, price):
self.description = description
self.__weight = weight # <1>
self.__price = price
self.__weight and self.__price are the internal attributes hidden in the class by the properties
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.
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")
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()