Python 3: Calling a Function from a class, self - python

I am trying to learn about classes, can someone explain to me why this code is not working. I thought when calling a function from a class, "self" is automatically ommitted, but the interpreter tells me that argument "a" is missing (he thinks self = 10).
#! coding=utf-8
class test:
def __init__(self):
"do something here"
def do(self,a):
return a**2
d = test.do
print(d(10))

Instantiate the class first:
d = test().do
print(d(10)) # prints 100
test.do is an unbound method, test().do is bound. The difference is explained in this thread: Class method differences in Python: bound, unbound and static.

You have to instantiate the class first:
d = test()
then you can call a method:
print(d.do(10))

if you want to use method statically you have to declare it in python
#! coding=utf-8
class test:
def __init__(self):
"do something here"
#staticmethod
def do(a):
return a**2
d = test.do
print(d(10)) #and that's work

Since you haven't instantiated the class (a fancy term for created) you can't be assigning methods to any random variable. Like already said, you must create the object first, whilst making sure the method you call is a part of the class you called or connected to the class in some way (such as creating another class and then communicating that class with the current class). So you should first type d=test() followed by d.do().
Also, remember that in your declaration of the method you crated a parameter so what you done was wrong in itself anyway, because when you declared the do function, you should have put within the brackets the number you wanted to send to the method to calculate its square. So you type test.do(10) and then the 10 is sent by the self reference to the method to be done whatever it is you told it to do.
One more thing: although it isn't a huge deal, it helps if all of your class names begin with a capital letter, as this is usually the 'pythonic' way to do things, and it also makes your code much easier to read, because when you first called the class, somebody could easily mistaken it for an ordinary function

class test:
def __init__(self):
"do something here"
def do(self,a):
return a**2
def __call__(self,a):
return self.do(a)
a = test
test.do(a,10)
#or
a = test().do
a(10)
#or
a = test()
test.do(a,10)
#or
a = test()
print(a(10))

Related

Pass closure to FunctionType in function

I have a code like this:
class A():
def __init__(self, a):
self.a = a
def outer_method(self):
def inner_method():
return self.a +1
return inner_method()
I want to write a test for inner_method. For that, I am using a code like this:
def find_nested_func(parent, child_name):
"""
Return the function named <child_name> that is defined inside
a <parent> function
Returns None if nonexistent
"""
consts = parent.__code__.co_consts
item = list(filter(lambda x:isinstance(x, CodeType) and x.co_name==child_name, consts ))[0]
return FunctionType(item, globals())
Calling it with find_nested_func(A().outer_method, 'inner_method') but it fails when calling to 'FunctionType' because the function cannot be created since 'self.a' stops existing in the moment the function stops being an inner function. I know the construction FunctionType can recive as an argument a closure that could fix this problem , but I don't know how to use it. How can I pass it?
The error it gives is the next one:
return FunctionType(item, globals())
TypeError: arg 5 (closure) must be tuple
Why are you trying to test inner_method? In most cases, you should only test parts of your public API. outer_method is part of A's public API, so test just that. inner_method is an implementation detail that can change: what if you decide to rename it? what if you refactor it slightly without modifying the externally visible behavior of outer_method? Users of the class A have no (easy) way of calling inner_method. Unit tests are usually only meant to test things that users of your class can call (I'm assuming these are for unit tests, because integration tests this granular would be strange--and the same principle would still mostly hold).
Practically, you'll have a problem extracting functions defined within another function's scope, for several reasons include variable capture. You have no way of knowing if inner_method only captures self or if outer_method performs some logic and computes some variables that inner_method uses. For example:
class A:
def outer_method():
b = 1
def inner_method():
return self.a + b
return inner_method()
Additionally, you could have control statements around the function definition, so there is no way to decide which definition is used without running outer_method. For example:
import random
class A:
def outer_method():
if random.random() < 0.5:
def inner_method():
return self.a + 1
else:
def inner_method():
return self.a + 2
return inner_method()
You can't extract inner_method here because there are two of them and you don't know which is actually used until you run outer_method.
So, just don't test inner_method.
If inner_method is truly complex enough that you want to test it in isolation (and if you do so, principled testing says you should mock out its uses, eg. its use in outer_method), then just make it a "private-ish" method on A:
class A:
def _inner_method(self):
return self.a + 1
def outer_method(self):
return self._inner_method()
Principled testing says you really shouldn't be testing underscore methods, but sometimes necessity requires it. Doing this things way allows you test _inner_method just as you would any other method. Then, when testing outer_method, you could mock it out by doing a._inner_method = Mock() (where a is the A object under test).
Also, use class A. The parens are unnecessary unless you have parent classes.

Why is a method of a Python class declared without "self" and without decorators not raising an exception?

I thought that the following code would result in an error because as far as I have read, a method in a Python class must either have "self" (or any other label, but "self" by convention) as its first argument, or "cls" or similar if the #classmethod decorator is used, or none if the #staticmethod decorator is used.
How come I get no error running this with Python 3.5 in the Terminal, even though test_method does not meet these requirements? It seems to work fine as a static method, but without the decorator.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
class MyClass:
def test_method(args):
print(args[1])
#staticmethod
def static_method():
print("static_method")
#classmethod
def class_method(cls):
print("class_method")
def main(args):
MyClass.test_method(args)
if __name__ == '__main__':
sys.exit(main(sys.argv))
Output:
$ python3 testscript.py "testing"
$ testing
EDIT:
My question could also be phrased differently, drawing attention away from self and to #staticmethod: "How come I'm getting a seemingly working static method without the #staticmethod decorator?"
In Python 2, functions defined in a class body are automatically converted to "unbound methods", and cannot be called directly without a staticmethod decorator. In Python 3, this concept was removed; MyClass.text_method is a simple function that lives inside the MyClass namespace, and can be called directly.
The main reason to still use staticmethod in Python 3 is if you also want to call the method on an instance. If you don't use the decorator, the method will always be passed the instance as the first parameter, causing a TypeError.
There is nothing special about this. In python 3 there is no difference between a function defined inside a class or a function defined outside a class. Both of them are normal functions.
The self that you are talking about here or maybe cls comes into picture only when you access the function through an instance. Hence here you didn't get any error.
However if you modify your code just a little bit to look like the following, then you'd get an error that you expected.
def main(args):
MyClass().test_method(args)
# Should throw an error
EDIT:
#staticmethod will work on both class instances like MyClass().test_method(args)and just a regular direct call like MyClass.test_method(args)
However a regular method(without self in it) can't be called on a class instance. So you will always have to call it as MyClass.test_method(args)
self isn't necessarily required. However, if you want to reference any variable or value that is associated with the object(instantiation of the class) (E.g. for a class about cars, it's speed, self.speed) you'll need to have self as a parameter in the function. For this reason, it's common practice to always have self as an argument, otherwise you aren't really using the class for the right reason.
EDIT:
This will actually throw an error if you do the following:
class a():
def __init__(self, x):
self.asd = x
def hello(x):
print(x)
>>> g = a(4)
>>> g.hello(5)
as when calling "hello", both "self" and "4" will be passed as parameters. It would work in the following instance, which is what I was saying above:
>>> g = a
>>> g.hello(4)
or
>>> a.hello(4)
To add on to the existing answers here and provide a code example:
class MyClass:
def __init__(self):
pass
def myStaticMethod():
print("a static method")
#staticmethod
def myStaticMethodWithArg(my_arg):
print(my_arg)
print("a static method")
MyClass.myStaticMethod()
MyClass.myStaticMethodWithArg("skhsdkj")
abc = MyClass()
abc.myStaticMethodWithArg("avc")
Try removing the #staticmethod decorator and rerunning the code and see what happens! (The very last call will fail since the method is passed in both self and the string input. By adding the decorator, we can guide the interpreter to perform our desired action)

Python - Is it possible to define an instance method inside another instance method?

Is it possible to do something like this? (This syntax doesn't actually work)
class TestClass(object):
def method(self):
print 'one'
def dynamically_defined_method(self):
print 'two'
c = TestClass()
c.method()
c.dynamically_defined_method() #this doesn't work
If it's possible, is it terrible programming practice? What I'm really trying to do is to have one of two variations of the same method be called (both with identical names and signatures), depending on the state of the instance.
Defining the function in the method doesn't automatically make it visible to the instance--it's just a function that is scoped to live within the method.
To expose it, you'd be tempted to do:
self.dynamically_defined_method = dynamically_defined_method
Only that doesn't work:
TypeError: dynamically_defined_method() takes exactly 1 argument (0 given)
You have to mark the function as being a method (which we do by using MethodType). So the full code to make that happen looks like this:
from types import MethodType
class TestClass(object):
def method(self):
def dynamically_defined_method(self):
print "two"
self.dynamically_defined_method = MethodType(dynamically_defined_method, self)
c = TestClass()
c.method()
c.dynamically_defined_method()

Python - how to properly extend classes to modify the operation of base methods

I am using some open-source python code that I need to make a slight modification to. Here is the starting situation.
Starting Situation
class BaseGatherer:
def get_string(self):
#a bunch of stuff I don't need to modify
return self.my_string #set with a hard value in __init__()
class BaseDoer:
def do_it(self, some_gatherer):
#a bunch of stuff I don't need to modify
string_needed = some_gatherer.get_string()
self.do_stuff(string_needed)
Externally, this would get used as follows:
my_gatherer = BaseGatherer()
my_doer = BaseDoer()
my_doer.do_it(my_gatherer)
What I need to change
What I need to do is two things:
Have BaseGatherer::get_string() return it's my_string with an inserted modification that changes each time it gets called. For example, the first time it gets called I get my_string[0:1] + 'loc=0' + my_string[1:], the second time I get 'my_string[0:1] + 'loc=10' + my_string[1:], etc.
Modify BaseDoer::do_it() to call BaseDoer::do_stuff() in a loop (until some stopping condition), each time setting string_needed with some_gatherer.get_string() which by #1 returns a different string with each call.
with the following restriction
The base code I am using is regularly updated and I don't want to modify that code at all; I want to be able to clone the repo I get it from and only possibly have to modify my "extended" code. It's ok to assume the names of the BaseGatherer and BaseDoer classes don't change in the base code, nor do the names of the methods I care about here, though some auxiliary methods that I don't need to modify will get updated (which is key for me).
My Question
My main question is what is the best, most Pythonic, way to do this?
My Attempt
Given the restriction I mentioned, my first inclination is to write derived classes of both BaseGatherer and BaseDoer which make the changes I need by writing new versions of the get_string() and do_it() methods respectively. But, I have a feeling that I should use function decorators to do this. I've read up on them a little and I get the basic idea (they wrap a function so that you can control/modify parameters passed to or values returned from the function you are wrapping without modifying that function?; please correct me if I am missing something crucial). But, I don't know how to implement this in the derived class, neither syntactically nor logically. For example, do I have to give the function decorator that I write a #classmethod decorator? If so, why?
Here is what I did. It works but I want to learn and understand a) what is the right way to do what I want and b) how to actually do it.
class DerivedGatherer(BaseGatherer):
def __init__(self):
super(DerivedGatherer, self).__init__() #I'm in Python 2.7 :(
self.counter = 0 #new variable not in BaseGatherer
#DON'T override BaseGatherer::get_string(), just write a new function
def get_string_XL(self):
self.counter += 10
return self.my_string[0:1] + 'loc=' + str(self.counter) + self.my_string[1:]
class DerivedDoer(BaseDoer):
def do_it_XL(self, some_derived_gatherer):
while(~some_stop_condition()):
string_needed = some_derived_gatherer.get_string_XL()
self.do_stuff(string_needed)
I would then call it just as above but create derived instances and call their XL methods instead of the base class one's.
But, there are problems with this that don't satisfy my goal/requirement above: both BaseGatherer::get_string() and BaseDoer::do_it() perform a lot of other functionality which I would have to just copy into my new functions (see the comment in them). This means when the code I'm using gets updated I have to do the copying to update my derived classes. But, I am ONLY changing what you see here: inserting something into the string that changes with each call and putting a loop at the end of do_it(). This is why I have a feeling that function decorators are the way to go. That I can wrap both get_string() and do_it() so that for the former I can modify the string with each call by looking at a local counter and for the second I can just have a loop that calls the base do_it() in a loop and passes a different string each time (it's ok to call do_it() multiple times).
Any help with suggestions on the best way to do this and how would be very greatly appreciated.
Thank you!
This is most easily done with plain inheritance, no repetition of code:
class DerivedGatherer(BaseGatherer):
def __init__(self):
super(DerivedGatherer, self).__init__()
self.counter = 0
def get_string(self):
self.counter += 10
super_string = super(DerivedGatherer, self).get_string()
return super_string[0:1] + 'loc=' + str(self.counter) + super_string[1:]
class DerivedDoer(BaseDoer):
def do_it(self, some_derived_gatherer):
while(~some_stop_condition()):
super(DerivedDoer, self).do_it(some_derived_gatherer)
As Martijn has explained to you, you can easily call a method in the base class from a method in the subclass. You can do it with super to insure you get the entire class structure as he shows. For illustration, though, if you are have a simple hierarchy with only one superclass and one subclass, this is how you can do it:
>>> class Foo(object):
... def xxx(self):
... return "Foo.xxx was called"
...
>>> class Bar(Foo):
... def xxx(self):
... return "Bar.xxx was called and then %s" % Foo.xxx(self)
...
>>> Bar().xxx()
'Bar.xxx was called and then Foo.xxx was called'

Using the self-parameter in python objects

I've got a question about defining functions and the self-parameter in python.
There is following code.
class Dictionaries(object):
__CSVDescription = ["ID", "States", "FilterTime", "Reaction", "DTC", "ActiveDischarge"]
def __makeDict(Lst):
return dict(zip(Lst, range(len(Lst))))
def getDict(self):
return self.__makeDict(self.__CSVDescription)
CSVDescription = __makeDict(__CSVDescription)
x = Dictionaries()
print x.CSVDescription
print x.getDict()
x.CSVDescription works fine. But print x.getDict() returns an error.
TypeError: __makeDict() takes exactly 1 argument (2 given)
I can add the self-parameter to the __makeDict() method, but then print x.CSVDescription wouldn't work.
How do I use the self-parameter correctly?
In python, the self parameter is implicitly passed to instance methods, unless the method is decorated with #staticmethod.
In this case, __makeDict doesn't need a reference to the object itself, so it can be made a static method so you can omit the self:
#staticmethod
def __makeDict(Lst): # ...
def getDict(self):
return self.__makeDict(self.__CSVDescription)
A solution using #staticmethod won't work here because calling the method from the class body itself doesn't invoke the descriptor protocol (this would also be a problem for normal methods if they were descriptors - but that isn't the case until after the class definition has been compiled). There are four major options here - but most of them could be seen as some level of code obfuscation, and would really need a comment to answer the question "why not just use a staticmethod?".
The first is, as #Marcus suggests, to always call the method from the class, not from an instance. That is, every time you would do self.__makeDict, do self.__class__.__makeDict instead. This will look strange, because it is a strange thing to do - in Python, you almost never need to call a method as Class.method, and the only time you do (in code written before super became available), using self.__class__ would be wrong.
In similar vein, but the other way around, you could make it a staticmethod and invoke the descriptor protocol manually in the class body - do: __makeDict.__get__(None, Dictionaries)(__lst).
Or, you could detect yourself what context its being called from by getting fancy with optional arguments:
def __makeDict(self, Lst=None):
if Lst is None:
Lst = self
...
But, by far the best way is to realise you're working in Python and not Java - put it outside the class.
def _makeDict(Lst):
...
class Dictionaries(object):
def getDict(self):
return _makeDict(self.__CSVDescription)
CSVDescription = _makeDict(__CSVDescription)

Categories