how to use a method with no args in python? - python

If I define a class a and a method blike this: (In Python2.7)
class a:
def b():
print("hello")
I can call this method neither by
a.b()
nor:
a_instance = a(); a_instance.b()
My questions are:
(1) Is there a way to call b?
(2) Is there any situation that this usage is meanful?
(3) I think b is neither a static method nor a instance method. Is b a class method? If not, what should be named to b?

or classmethod decorator which takes class object as first instance.
Is there a way to call b?
Yes you could either make it a static method or an instance method and call it accordingly. Below i make it a static method so you can call it on any instance or directly on the class object a
class a:
#classmethod
def b(cls):
print("hello")
a.b() #'hello'
Is there any situation that this usage is meanful?
What usage? static methods? yes there is, and it depends on your architecture. classmethods can be used as factory functions? returning new instances of classes.
I think b is neither a static method nor a instance method. Is b a class method? If not, what should be named to b?
i, too, don't think it is either. I believe it is just a function defined inside of a class body
I was confused about defining a function inside of a class and asked a similar question here

b is a static method. Just add the #staticmethod decorator.
class a:
#staticmethod
def b():
print("hello")
Also, you shouldn't really do this, but if you wanted to call b() without changing the class, you could do a().b.__func__().

Just in case this isn't obvious:
class a:
def b(self): # a normal "instance method" -- note "self"
print("hello")
aa = a() # an instance
aa.b() # call with no parameters
Here, b has no parameters because self is implied when called on an instance of the class.

Related

staticmethod decorator seems pointless

I was reading about the #staticmethod in Python when I came across tge following code:
class MyClass:
my_var = 0
#staticmethod
def static_method():
MyClass.my_var += 1
I just don't understand exactly why you can write a code like this... Doesn't it defeat the purpose of this method to be static?
I get it that there's also the fact that the first parameter won't be a class/instance reference, but... Still weird to call this decorator like that if I still can access class variables, no?
And if I can access class variables, why everywhere I read about it says that I cannot, even though I just clearly did with the code above? Is it just because I'm doing it wrong?
The idea that a static method can't modify class state is based on the idea that the static method doesn't receive a reference to the class as an argument like a class method does. However, in this case, a reference to the class is provided as a hard-coded value.
One reason for defining a static method rather than a class method is to guarantee that you modify the attribute of a specific class, rather than a possible subclass.
class A:
my_var = 0
#classmethod
def foo(cls):
cls.my_var += 1
#staticmethod
def bar():
A.my_var += 1
class B(A):
my_var = 0
A call to B.foo will modify B.my_var, not A.my_var. A call to B.bar will modify A.my_var.

How to pass an instance method, that uses instance variables, as argument to another function?

I want to pass a method foo of an instance of a class A to another function run_function. The method foo will use instance variables of its class A.
Here is a minimal example, in which the instance variable of A is simply self.a_var, and foo just prints that variable.
class A:
def __init__(self,a_var):
self.a_var=a_var
def foo(self):
print(self.a_var)
class B:
def __init__(self, A):
self.A=A
# EDIT (comment to compile)
self.A.do_something()
def run_function(self):
self.A.foo()
def run_function_2(self, bar):
bar()
myA = A(42)
myA.foo()
# Current implementation
myB=B(myA)
myB.run_function()
# Better(?) implementation
myB.run_function_2(myA.foo)
At the moment I pass the instance myA of class A to the instance of B and explicitly call self.A.foo(). This forces the name of the function of Ato be foo. Which is stupid.
The better (?) implementation passes the function of the instance to run_function2. This works, but I am not sure if this is "safe".
Question:
Are there any loopholes that I don't see at the moment?
The important part is, that the method foo, that is passed, needs to access instance variables of the (its) class instance. So, will foo that is called inside run_function_2 always have access to all instance variables of myA?
Is there a better way to implement this?
EDIT: I forgot to add, that class B will always have an instance of A, since it has to do_something with that instance. Maybe that will change something(?). Sorry!
For your second implementation, have you considered the following:
>>> myAa = A(42)
>>> myAb = A(43)
>>> myB = B(myAb)
>>> myB.run_function_2(myAa.foo)
42
This might not be what you want. How about using getattr() and just passing in the desired method name:
>>> class C:
... def __init__(self, A):
... self.A = A
... def run_fct(self, bar):
... fct = getattr(self.A, bar)
... fct()
...
>>> myC = C(myAa)
>>> myC.run_fct('foo')
42
To answer your questions:
Any function executed in the context of an object instance will have access to the instance variables.
There may be a better way to implement this, you could try defining an interface for class A and other classes that might be like it. The you know that the function will always be called foo(). If not, I'd question why it is you need to have some object call an arbitrary method on another object. If you can give more concrete examples about what you're trying to do it would help.
The main difference between run_function and run_function_2 is that the former calls foo on the object that was given to the B() constructor. run_function_2 is independent of what object is saved as self.A; it just calls the function/method you give it. For example
class A:
def __init__(self,a_var):
self.a_var=a_var
def foo(self):
print(self.a_var)
class B:
def __init__(self, A):
self.A=A
def run_function(self):
self.A.foo()
def run_function_2(self, bar):
bar()
myA = A(42)
myB = B(myA)
myA2 = A(3.14)
myB.run_function()
myB.run_function_2(myA.foo)
myB.run_function_2(myA2.foo)
Output
42
42
3.14
Are there any loopholes that I don't see at the moment?
These two ways of calling methods are fine. Though I agree that function_run_2 is more convenient since it doesn't fix the method name, it makes you ask... what's the purpose of giving an A object to the B constructor in the first place if it's never used?
The important part is, that the method foo, that is passed, needs to access instance variables of the (its) class instance. So, will foo that is called inside run_function_2 always have access to all instance variables of myA?
Yes. run_function_2 arguments requires a function. In this case, you pass myA.foo, an object myA's method defined in class A. When you call foo inside run_function_2, you are only dealing with attributes variables of the instance myA; this is the idea of encapsulation in classes.
Is there a better way to implement this?
Answering also your question on safety, it's perfectly safe. Functions and methods are objects in Python, and they can be passed around like values. You're basically leaning on the idea of function currying or partial functions. See How do I pass a method as a parameter in Python. These two ways are fine.

Can Python Staticmethod Call Another Local Method?

In Python, within a class, can a staticmethod call on another local function/method defined within the same class?
I tried the following code and obtained an error message saying foo1() is not defined.
class trialOne(object):
#staticmethod
def foo1():
a = 3.1
return a
#staticmethod
def foo():
a = foo1()
return a
obj = trialOne()
b = obj.foo()
class Tester:
def local(self):
print "I'm a local!"
#staticmethod
def another_stat():
print "I'm a static!"
#staticmethod
def stat(inst):
inst.local()
Tester.another_stat()
t = Tester()
Tester.stat(t)
# Out:
# I'm a local!
# I'm a static!
Yes, you can! By definition, instance methods need an instance to associate themselves with, but as long as you have that instance, you can call local methods just as you normally would.
To go into this in a little more depth, there's nothing special about the word self. That's a variable just like any other. Any instance method of a class MUST take in an instance of that class as its first parameter, and it's convention to call that parameter self, but you could just as easily use any other name.
If it helps you understand the distinction, these two statements are semantically equivalent:
t.local()
Tester.local(t)
The first is just syntactic sugar for the second. The second is using the class name to reference a method of the Tester class, then passes in the instance as the first parameter. The first simply pretends that local is a field of t and calls it, but that call is transformed into Tester.local(t) by the Python interpreter.
Thus, calling a static method is the same syntax as Tester.local(t), except the first parameter does not have to be an instance of that class.
So classmethods and staticmethods are called in the same way, but the difference is that a class method "knows" what class it's coming from. The first parameter of a class method is always a variable that contains the class that it's being invoked from. That way if the method is inherited, it knows which method it's coming from, where a staticmethod would not know. In your comment, you said this:
#classmethod
def stat(cls):
cls.another_stat()
In this example, cls is a variable that contains the class that the method is being called from, not an instance of the class that it is being called from. That is why you can call static methods with cls - because it is equivalent to Tester

How to use method of one class to another class in different files in python

I am quite new to python, so pardon me for basic question. I tried google for past few days but could not make it in my program.
Can anyone show me a good example how can I use method from One class to another in python and what is significance of __init__ while defining class.
I am using python2.7
Thanks in anticipation.
To use a method defined in one class inside of another class, you have several options:
Create an instance of B from within one of A's methods, then call B's method:
class A:
def methodInA():
b = B()
b.methodInB()
If appropriate, use the concept of inheritance (one of the defining concepts of object-oriented design) to create a subclass of the original class whose method(s) you wish to use:
class B(A):
...
__init__() is a class initializer. Whenever you instantiate an object you are invoking __init__() whether or not it is explicitly defined. It's main purpose is to initialize class data members:
class C:
def __init__(self, name):
self.name = name
def printName(self):
print self.name
c = C("George")
c.printName() # outputs George
With __init__() defined, in particular with the additional argument name in this example, you are able to differentiate between would-be generically constructed instances by allowing for different initial states from instance to instance.
There are 2 issues here:
First: Using method of class A in class B, both classes in different files
class A:
def methodOfA(self):
print "method Of A"
let the above class be in file a.py Now the class B is supposed to be in b.py. Both a.py and b.py are assumed to be on the same level or in the same location. Then b.py would look like:
import a
class B:
def methodOfB(self):
print "Method of B"
a.A().methodOfA()
You can also do this by inherting A in B
import a
class B(a.A):
def methodOfB(self):
print "Method of B"
self.methodOfA()
there are several other ways to use A in B. I will leave it to you to explore.
Now to your second question. The use of __init__ in a class. __init__ is not a constructor, as popularly believed and explained above. It is, as the name suggests, an initialization function. It is called only after the object has already been constructed and it is implicitly passed the object instance as the first argument, as signified by self in its argument list.
The actual constructor in python is called __new__, which does not need a object to call it. This is actually a specialized Static method, which receives the class instance as the first argument. __new__ is exposed for overwriting only if the class inherits form the object base class of python
Whatever other arguments are passed while creating an object of a class, first go to __new__ and then are passed with the object instance to the __init__, if it accepts them.
The init function is what is called a constructor function. When you create an instance of a class object = myClass(), init is the function that is automatically called. i.e.
That being said, to call a function from one class to another, you need to call an instance of the second class inside the first one, or vice versa. for eg.
class One():
def func(self):
#does sometthing here
class Two():
def __init__(self):
self.anotherClass = One()
#Now you can access the functions of the first class by using anotherClass followed by dot operator
self.anotherClass.func()
#When you call the main class. This is the time the __init__ function is automatically called
mainClass = Two()
Another way to access from another class is the use of oop concept called Inheritance.
class One():
def __init__(self):
print('Class One Called')
def func(self):
print('func1 Called')
class Two(One):
def __init__(self):
One.__init__(self,) #This basically creates One's instance
print('Main Called')
c= Two()
c.func()
The output for this is:
Class One Called
Main Called
func1 Called

Should I use super() every time I call parent function or only inside overridden functions?

If we override parent class's method, we can use super() to avoid mention of parent class's name - that's clear.
But what about case, when we just use in subclass some function defined in parent class? What is preferable way: to use super().parent_method() or self.parent_method()? Or there's no difference?
class A:
def test1(self):
pass
def test_a(self):
pass
class B(A):
def test1(self):
super().test1() # That's clear.
def test_b(self):
# Which option is better, when I want to use parent's func here?
# 1) super().test_a()
# 2) self.test_a()
pass
Usually you will want to use self.test_a() to call an inherited method. However, in some rare situations you might want to use super().test_a() even though it seems to do the same thing. They're not equivalent, even though they have the same behavior in your example.
To explore the differences, lets make two versions of your B class, one with each kind of call, then make two C classes that further extend the B classes and override test_a:
class A(object):
def test_a(self):
return "A"
class B1(A):
def test_b(self):
return self.test_a() + "B"
class B2(A):
def test_b(self):
return super().test_a() + "B"
class C1(B1):
def test_a(self):
return "C"
class C2(B2):
def test_a(self):
return "C"
When you call the test_b() method on C1 and C2 instances you'll get different results, even though B1 and B2 behave the same:
>>> B1().test_b()
'AB'
>>> B2().test_b()
'AB'
>>> C1().test_b()
'CB'
>>> C2().test_b()
'AB'
This is because the super() call in B2.test_b tells Python that you want to skip the version of test_a in any more derived class and always call an implementation from a parent class. (Actually, I suppose it could be a sibling class in a multiple inheritance situation, but that's getting even more obscure.)
Like I said at the top, you usually want to allow a more-derived class like the Cs to override the behavior of the inherited methods you're calling in your less-derived class. That means that most of the time using self.whatever is the way to go. You only need to use super when you're doing something fancy.
Since B is an A, it has a member test_a. So you call it as
self.test_a()
B does not overwrite A.test_a so there is no need to use super() to call it.
Since B overwrites A.test1, you must explicitly name the method you want to call.
self.test1()
will call B.test1, while
super().test1()
will call A.test1.
Firstly both the ways super().test_a() and self.test_a() will result in execution of method test_a().
Since Class B does not override or overwrite test_a() I think use of self.test_a() will be much efficient as self is a mere reference to the current object which is there in memory.
As per documentation, super() results in creation of proxy object which contains other methods also. Owing to this reason I feel self will be the correct approach in your case.
If we override parent class's method, we can use super() to avoid
mention of parent class's name - that's clear.
actually super() is not syntactic sugar, its purpose is to invoke parent implementation of a certain method.
You have to use super() when you want to override a parent method, you don't have to use super() when instead you want to overwrite a method. The difference is that in the first case you want to add extra behavior (aka code execution) before or after the original implementation, in the second you want a completely different implementation.
You can't use self.method_name() in an override, the result will be a recursion error! (RuntimeError: maximum recursion depth exceeded)
Example:
class A:
def m(self):
print('A.m implementation')
class B(A):
def m(self):
super().m()
print('B.m implementation')
class C(A):
def m(self):
print('C.m implementation')
class D(A):
def m(self):
self.m()
a = A()
a.m()
b = B()
b.m()
c = C()
c.m()
d = D()
d.m()
Given a base class A, with a method m, B extends A by overriding m, C extends A by overwriting m, and D generates an error!
EDIT:
I just realized that you actually have 2 different methods (test_a and test_b). My answer is still valid, but regarding your specific scenario:
you should use self.test_a() unless you override/overwrite that method in your class B and you want to execute the original implementation... so we can say that calling super().test_a() or self.test_a() it's the same given that you'll never override/overwrite the original test_a() in your subclasses... however is a nonsense to use super() if not for an override/overwrite

Categories