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
Related
I have searched all the related this stackoverflow question but its not satisfied my issue.
BaseHandler.py
class BaseHandler(object):
def __init__(self, rHandler, path, param):
self._rHandler = rHandler
self._server = self._rHandler.server
self._path = path
self._param = param
def _getElement(self, name):
return name + "append"
MyClass.py
class MyClass(BaseHandler.BaseHandler):
def getA(self):
print "Some info"
def getB(self):
el = self._getElement("T") #baseclass method
print ebl
I wanted to call getB from the below class.
RThread.py
import MyClass
class RThread(object):
def someMethod(self):
clr = MyClass.MyClass
clr.getB()
I am getting the following error:
TypeError: unbound method getB() must be called with MyClass instance as first argument (got nothing instead)
When I try the following:
clr = MyClass.MyClass()
I am getting the following error:
init() takes exactly 4 arguments (1 given)
So kindly help me how to call this method from different class.
You need to instantiate the class in order to call a method on it.
def someMethod(self):
clr = MyClass.MyClass(*args)
clr.getB()
In the case you want the method to be callable from the class you need to use either #staticmethod or #classmethod
#staticmethod
def getB():
return self._getElement("T")
However, you are using the self. notation which requires an instance. So you would need to flag the _getElement method with #staticmethod as well. Static methods do not have access to the parent class. You can use the #classmethod decorator to do so.
#classmethod
def getB(cls):
return cls._getElement("T")
You're not calling the method correctly; you need to create an object. This is how you create an object, which is what you were doing, except you weren't passing in enough parameters.
clr = MyClass.MyClass()
Since MyClass inherits from BaseHandler and you did not override its constructor, you're using the constructor from BaseHandler, which has four arguments, one of which is self.
def __init__(self, rHandler, path, param):
...
So, try something like this:
clr = MyClass.MyClass(arg1, arg2, arg3)
clr.getB()
I have the following class and class variables:
class MyClass:
class_var_1 = "a"
class_var_2 = run_class_method()
#classmethod
def run_class_method(cls):
return "ran class method"
However, the interpreter says that run_class_method isn't defined. Using MyClass.run_class_method() doesn't work either. Coming from a java background, I don't understand why this doesn't work. So, how can I fix it?
Additionally, I discovered that this works if I define class variables at the end of the class. Is this considered bad practice in python?
Class body in python is an executable context, not like Java that only contains declaration. What this ultimately means is that sequence of execution is important within a class definition.
To quote the documentation:
class definition is an executable statement.
...
The class’s suite is then executed in a new execution frame (see Naming and binding), using a newly created local namespace and the original global namespace. (Usually, the suite contains mostly function definitions.) When the class’s suite finishes execution, its execution frame is discarded but its local namespace is saved. [4] A class object is then created using the inheritance list for the base classes and the saved local namespace for the attribute dictionary. The class name is bound to this class object in the original local namespace.
Some more lengthier explanations.
If you want to call a function to define a class variable, you can do it with one of these ways:
use staticmethod:
class MyClass:
def _run_instance_method():
return "ran instance method"
run_instance_method = staticmethod(_run_instance_method)
class_var_1 = "a"
class_var_2 = _run_instance_method() # or run_instance_method.__func__()
or define it as a standalone function:
def run_method():
return "ran method"
class MyClass:
class_var_1 = "a"
class_var_2 = run_method()
# optional
run_method = staticmethod(run_method)
or access the original function with __func__ and provide a dummy cls value:
class MyClass:
#classmethod
def run_class_method(cls):
return "ran class method"
class_var_1 = "a"
class_var_2 = run_class_method.__func__(object())
or set the class variables after class creation:
class MyClass:
#classmethod
def run_class_method(cls):
return "ran class method"
class_var_1 = "a"
MyClass.class_var_2 = MyClass.run_class_method()
MyClass is not yet defined when its class attributes are still being defined, so at the time class_var_2 is being defined, MyClass is not yet available for reference. You can work around this by defining class_var_2 after the MyClass definition block:
class MyClass:
class_var_1 = "a"
#classmethod
def run_class_method(cls):
return "ran class method"
MyClass.class_var_2 = MyClass.run_class_method()
The first thing to note is that Java does not have class methods. It has static methods and regular methods. A regular method receives the instance it was called from as an argument. A class method receives the class is was called from (not the class it is defined on) as an argument. Static methods get nothing special and act like normal functions -- static methods are just a way of grouping logically related methods.
The second thing to note is that a Java class definition is parsed into a separate class definition and an implicit static constructor. When initialising class attributes this enables you to call methods before they are defined in the class body. This is because in the actual program these statements will be called only after the class has been created/loaded into memory. In Python there is no such distinction. Instead, to create a class you execute a series of statements inside a specialised namespace, and this is then used to create the class. Like in a body of a function or module block of code you cannot use a variable before it is exists. This includes using the class within the class body (as it doesn't exist yet!)
eg. This is valid Java:
class X {
static int i = 1;
static X obj = newInstance();
// ^-- executed after the class has been created, but is still being initialised.
static X newInstance() {
return new X();
}
}
But this is not valid Python
class X:
val = 1
obj = new_instance()
# ^-- We're still in the body of X, and neither new_instance nor X has been created yet
#classmethod
def new_instance(cls):
return cls()
# even if new_instance was defined before obj, Python still wouldn't be able to fill
# in the cls argument as X still doesn't exist when new_instance is first invoked
In Python you must do the static construction of your class explicitly. Bear in mind this is exactly what would happen in Java, it's just hidden behind syntactic sugar.
class X:
val = 1 # this can still be done in the class body as it doesn't need the class
obj = None # not necessary, but can help type checkers know that X has an
# attribute obj -- you can use type annotations to further help
#classmethod
def new_instance(cls):
return cls()
# explicit class initialisation of attributes
X.obj = X.new_instance()
Another way to do this would be to define a parent class that has control over the creation of its subclasses (or a metaclass). Below, we use __init_subclass__ in a parent class to set the attribute during class creation.
class InitVar():
def __init_subclass__(cls, varname, funcname, **kwargs):
class_method = getattr(cls, funcname)
setattr(cls, varname, class_method())
class MyClass(InitVar, varname="class_var_2", funcname="run_class_method"):
class_var_1 = "a"
#classmethod
def run_class_method(cls):
return "ran class method"
print(MyClass.class_var_2)
# ran class method
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).
I am confused even after checking many questions asked in SO. I have 2 different class (2 different script) & I want to inherit super class's __init__ method's parameters.
script1.py
class MainClass():
def __init__(self,params):
self.one=params['ONE']
self.two=params['TWO']
self.three=params['THREE']
self.four=params['FOUR']
self.five=params['FIVE']
def a():
#---------
#somecode
#Initializing other class's object to access it's method.
s=SubClass() #HERE I WANT TO PASS 'PARAMS' (WHICH IS A DICTIONARY)
s.method1(....)
script2.py
class SubClass(SuperClass):
def __init__(self,params):
#Here I want all the parameters inside the 'param' in super class.
#(one,two,three...., etc).
#By checking some SO questions, I changed class SubClass() -->
#class Subclass(SuperClass) & below line:
MainClass.__init__(self,params) #But technically I don't have anything
#in param in subclass.
def method1():
#some code...
Since sub class's param doesn't have anything, It gives me an error:
self.one=params['ONE']
TypeError: 'int' object has no attribute '__getitem__'
I am not getting:
How can I access all the parameters of super class to sub class in a simplest way? I don't want to pass individual arguments (like self.one, self.two..) to the sub class.
If I am calling third class inside SubClass -> method1 --> Call 3rd class same as passing 'params'. Is it possible?
Is this what you need?
script1.py
class MainClass():
def __init__(self,params):
# Save params for use by a
self.params = params
self.one=params['ONE']
self.two=params['TWO']
...
self.five=params['FIVE']
def a():
s=SubClass(self.params)
s.method1(...)
script2.py
class SubClass(SuperClass):
def __init__(self,params):
MainClass.__init__(self,params)
def method1():
#some code...
You can pass any and all the non-keyword arguments from the subclass's __init__()to the superclass's like this:
class SubClass(SuperClass):
def __init__(self, *params):
MainClass.__init__(self, *params)
...
This same idea will work for other methods, too.
I have some functionality wrapped up in a Python class (classa). classa inherits from another class supera.
I want exactly the same functionality as classa except that I want to inherit from superb.
I could just copy the class classa to a new class classb and then change the superclass for classb but obviously this very tacky, a maintenance headache and and I'm quite sure there's much better way - can anyone tell me what it is ?
EDIT: Thanks for answers so far. I should have said initially the my classa invokes super in its methods in order to invoke supera methods. It seems that this has some significance when looking at mixins as an option
This can be done with Python's multiple inheritance if none of the methods need to invoke super().
class Dog(object):
name = "Spot"
class Cat(object):
name = "Whiskers"
class SpeakingAnimalMixin(object):
def speak(self):
print "My name is", self.name, "and I can speak!"
class SpeakingDog(SpeakingAnimalMixin, Dog):
pass
class SpeakingCat(SpeakingAnimalMixin, Cat):
pass
SpeakingDog().speak()
My name is Spot and I can speak!
If you do need to invoke super() from a method then you need to create the class dynamically. This works fine, but the generated class's name will be less helpful and IDEs and other static analysis tools may be less useful.
You can create the class using a function, passing the superclass as an argument:
def make_speaking_animal_class(SpeechlessAnimal):
class SpeakingAnimal(SpeechlessAnimal):
def get_name(self):
return "Speaking " + super(SpeakingAnimal, self).get_name()
def speak(self):
print "My name is", self.get_name()
return SpeakingAnimal
class Dog(object):
def get_name(self):
return "Spot"
class Cat(object):
def get_name(self):
return "Whiskers"
SpeakingDog = make_speaking_animal_class(Dog)
SpeakingCat = make_speaking_animal_class(Cat)
SpeakingCat().speak()
My name is Speaking Whiskers
However as mentioned, the class's __name__ attribute may not be what you expect.
print SpeakingDog
print SpeakingDog()
<class '__main__.SpeakingAnimal'>
<__main__.SpeakingAnimal object at 0x1004a3b50>
You can fix this by assigning them unique __name__ attributes yourself:
SpeakingDog.__name__ = 'SpeakingDog'
print SpeakingDog
<class '__main__.SpeakingDog'>
(Credit to Andrew Jaffe for suggesting this in an answer, but he deleted it.)
There's another way to create a class dynamically, but I discourage you from using it unless you need to; it's even less clear. The type function has a second use, apart from its main one of determining the class of an object: it can be used to dynamically create a new class.
When used this way, the type function takes three parameters:
name, the __name__ the new class will have.
bases, a tuple of of base classes that the new class will inherit from.
dict, a dictionary containing the methods and attributes the new class will have.
You could use it like this:
def make_speaking_animal_class(SpeechlessAnimal, name):
def get_name(self):
return "Speaking " + super(SpeakingAnimal, self).get_name()
def speak(self):
print "My name is", self.get_name()
bases = (SpeechlessAnimal,)
# We need to define SpeakingAnimal in a variable so that get_name can refer
# to it for the super() call, otherwise we could just return it directly.
SpeakingAnimal = type(name, bases, {
'get_name': get_name,
'speak': speak
})
return SpeakingAnimal
class Dog(object):
def get_name(self):
return "Spot"
class Cat(object):
def get_name(self):
return "Whiskers"
SpeakingDog = make_speaking_animal_class(Dog, 'SpeakingDog')
SpeakingCat = make_speaking_animal_class(Cat, 'SpeakingCat')
SpeakingDog().speak()
SpeakingCat().speak()
My name is Speaking Spot
My name is Speaking Whiskers