Python module, class, method basicks - python

I am completely new to python and I have experienced, for me, strange behaviour. I have two files: foo.py and test.py
test.py:
from foo import Foo
f = Foo()
f.bar(1)
When my foo.py looks as this:
class Foo:
def bar(n):
print n
I get error message:
Traceback (most recent call last):
File "test.py", line 3, in <module>
f.bar(1)
TypeError: bar() takes exactly 1 argument (2 given)
When my foo.py looks as this:
class Foo:
def bar(x,n):
print n
I get result:
1
Why is that? Why do I need to have two params declared, even though I want to have method which takes only one? Thank you

The first argument in a method is supposed to be the object on which the method is called. That is when you call f.foo(1) it means that foo will be called with the arguments foo(f, 1). Normally one calls the first argument for self, but python doesn't care about the name, your second example the object f will be sent via the x parameter.

The reason is because Python expects the first argument to be object which is calling the function. If you're familiar with C++ or Java, it's similar to the "this" keyword. Just that Python is more particular that you explicitly declare this rather than implicitly. The standard coding convention suggests that you use "self" as the first argument, but you could use any really.
In your example,
from foo import Foo
f = Foo()
f.bar(1)
When you call the function bar, which is inside the class Foo, it can be called as Foo.bar(f,n) or f.bar(n). Here, self is 'f' or referring to the current object calling the class.
I suggest having a look at Why explicit self has to stay for clearer understanding.

Related

Callable modules with parameters

Is it possible to make a module callable with parameters?
I am trying to make a callable module on Python, following the question and its answers Callable modules, like so:
foo.py
import sys
class foo(object):
def __call__(self):
return 'callable'
sys.modules[__name__] = foo()
then I call it:
import foo
print(foo()) # 'callable'
but my objective is to pass a parameter in the callable module:
print(foo('parameter'))
Any ideas how can I accomplish that?
There's nothing special about the class you created (it's not even a ModuleType subclass), so there's nothing special about its __call__ method. If you want to call it with arguments, just add parameters to the __call__ definition:
import sys
class foo(object):
def __call__(self, x):
return f'callable, and called with {x}'
sys.modules[__name__] = foo()
And now, you can pass it an argument, exactly like any other callable object:
import foo
print(foo('hello'))
And the output is:
callable, and called with hello
From the comments, you tried to do this:
def __call__(a, self):
return a
But, like all methods in Python, __call__ wants self to come first. It doesn't care about the names (unless you call it with keyword arguments), just the order: the first parameter gets the receiver (the foo in foo('hello')), even if it you called that parameter a, and the second parameter gets the first normal argument (the 'hello'), even if you called that parameter self.
So, you're passing the module foo as the first parameter, a, and you return a, so it returns foo.
Which is why you got this:
<sta.foo object at 0x10faee6a0>
That isn't an error, that's the perfectly valid output that you get when you print out an instance of a class that doesn't define __repr__ or __str__.

Static method syntax confusion

This is how we make static functions in Python:
class A:
#staticmethod
def fun():
print 'hello'
A.fun()
This works as expected and prints hello.
If it is a member function instead of a static one, we use self:
class A:
def fun(self):
print 'hello'
A().fun()
which also works as expected and prints hello.
My confusion is with the following case:
class A:
def fun():
print 'hello'
In the above case, there is no staticmethod, nor self. Python interpreter is okay with this definition. However, we cannot call it either of the above methods, namely:
A.fun()
A().fun()
both gives errors.
My question is: Is there any way that I can call this function? If not, why Python do not give me a syntax error in the first place?
Python doesn't give you a syntax error, because the binding of a method (which takes care of passing in self) is a runtime action.
Only when you look up a method on a class or instance, is a method being bound (because functions are descriptors they produce a method when looked up this way). This is done via the descriptor.__get__() method, which is called by the object.__getattribute__() method, which Python called when you tried to access the fun attribute on the A class or A() instance.
You can always 'unwrap' the bound method and reach for the un-wrapped function underneath to call it directly:
A.fun.__func__()
Incidentally, that's exactly what staticmethod does; it is there to 'intercept' the descriptor binding and return the raw function object instead of a bound method. In other words, staticmethod undoes the normal runtime method binding:
Demo:
>>> class A(object): pass
...
>>> def fun(): print 'hello!'
...
>>> fun.__get__(None, A) # binding to a class
<unbound method A.fun>
>>> fun.__get__(None, A)() # calling a bound function, fails as there is no first argument
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method fun() must be called with A instance as first argument (got nothing instead)
>>> fun.__get__(None, A).__func__ # access the wrapped function
<function fun at 0x100ba8378>
>>> staticmethod(fun).__get__(None, A) # staticmethod object just returns the function
<function fun at 0x100ba8378>
>>> staticmethod(fun).__get__(None, A)() # so calling it works
hello!

Calling a function within my class isn't working

class MyClass(object):
def f(self):
return 'hello world'
Everything i have been reading here and on other websites that with this code, if i run MyClass.f() it should return with hello world but instead i keep getting
Traceback (most recent call last):
File "C:\Users\Calvin\Desktop\CS_Semester_Project\testing.py", line 5, in <module>
MyClass.f()
TypeError: unbound method f() must be called with MyClass instance as first argument (got nothing instead)
I have no idea what i'm doing wrong, any help would be very appreciated.
Do this:
myCls = MyClass()
myCls.f()
As error saying you f method require instance while you calling it like a static function
You can read more about python classes in tutorial in methods section
The error is telling you that f() must be called on an instance of type MyClass, not on MyClass itself.
You need to create an instance of MyClass:
obj = MyClass()
In this case obj would be an instance of MyClass.
Then you need to call f() on that object:
obj.f()
The error message is confusing because of the way that methods are called in Python. When you call obj.f(), obj is implicitly passed to f() as the first argument. That's why you have to write
def f(self):
...
self is going to refer to obj when you call obj.f().
Knowing that, if you take another look at the error message:
TypeError: unbound method f() must be called with MyClass instance as first argument (got nothing instead)
It makes more sense. It says that f() was expecting an argument, (specifically an instance of MyClass) and didn't get one because tried to call it on a type rather than an instance of a type.

Bound Python method accessed with getattr throwing:" takes no arguments (1 given) " [duplicate]

This question already has answers here:
Why do I get a TypeError that says "takes no arguments (1 given)"? [duplicate]
(4 answers)
Closed 6 years ago.
Something rather odd is happening in an interaction between bound methods, inheritance, and getattr that I am failing to understand.
I have a directory setup like:
/a
__init__.py
start_module.py
/b
__init__.py
imported_module.py
imported_module.py contains a number of class objects one of which is of this form:
class Foo(some_parent_class):
def bar(self):
return [1,2,3]
A function in start_module.py uses inspect to get a list of strings representing the classes in imported_module.py. "Foo" is the first of those strings. The goal is to run bar in start_module.py using that string and getattr.*
To do this I use code in start_module of the form:
for class_name in class_name_list:
instance = getattr(b.imported_module, class_name)()
function = getattr(instance, "bar")
for doodad in [x for x in function()]:
print doodad
Which does successfully start to iterate over the list comprehension, but on the first string, "bar", I get a bizarre error. Despite bar being a bound method, and so as far as I understand expecting an instance of Foo as an argument, I am told:
TypeError: bar() takes no arguments (1 given)
This makes it seem like my call to function() is passing the Foo instance, but the code is not expecting to receive it.
I really have no idea what is going on here and couldn't parse out an explanation through looking on Google and Stack Overflow. Is the double getattr causing some weird interaction? Is my understanding of class objects in Python too hazy? I'd love to hear your thoughts.
*To avoid the anti-pattern, the real end objective is to have start_module.py automatically have access to all methods of name bar across a variety of classes similar to Foo in imported_module.py. I am doing this in the hopes of avoiding making my successors maintain a list for what could be a very large number of Foo-resembling classes.
Answered below: I think the biggest takeaways here are that inspect is very useful, and that if there is a common cause for the bug you are experiencing, make absolutely sure you've ruled that out before moving on to search for other possibilities. In this case I overlooked the fact that the module I was looking at that had correct code might not be the one being imported due to recent edits to the file structure.
Since the sample code you posted is wrong, I'm guessing that you have another module with the Foo class somewhere - maybe bar is defined like this
class Foo(object):
def bar(): # <-- missing self parameter
return [1,2,3]
This does give that error message
>>> Foo().bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() takes no arguments (1 given)
Class method have a self argument that is essentially automatically passed. It is just the class instance on which you are calling the method. You don't need to pass another parameter.
I'm not able to reproduce the error you're getting. Here's my attempt at a short, self-contained compilable example, run from the Python shell:
>>> class Foo(object):
def bar(self):
print("Foo.bar!")
>>> import __main__ as mod
>>> cls = getattr(mod, "Foo")
>>> inst = cls()
>>> func = getattr(inst, "bar")
>>> func()
Foo.bar!
Perhaps you can try adapting your inspect based code to an example like this one and see where it is going wrong.

Class instantiation and 'self' in python

I know a ton has been written on this subject. I cannot, however, absorb much of it. Perhaps because I'm a complete novice teaching myself without the benefit of any training in computer science. Regardless, maybe if some of you big brains chime in on this specific example, you'll help other beginners like me.
So, I've written the following function which works just fine when I call it (as a module?) as it's own file called 'funky.py':
I type the following into my terminal:
python classy.py
and it runs fine.
def load_deck():
suite = ('Spades', 'Hearts')
rank = ('2', '3')
full_deck = {}
i = 0
for s in suite:
for r in rank:
full_deck[i] = "%s of %s" % (r, s)
i += 1
return full_deck
print load_deck()
When I put the same function in a class, however, I get an error.
Here's my code for 'classy.py':
class GAME():
def load_deck():
suite = ('Spades', 'Hearts')
rank = ('2', '3')
full_deck = {}
i = 0
for s in suite:
for r in rank:
full_deck[i] = "%s of %s" % (r, s)
i += 1
return full_deck
MyGame = GAME()
print MyGame.load_deck()
I get the following error:
Traceback (most recent call last):
File "classy.py", line 15, in <module>
print MyGame.load_deck()
TypeError: load_deck() takes no arguments (1 given)
So, I changed the definition line to the following and it works fine:
def load_deck(self):
What is it about putting a function in a class that demands the use of 'self'. I understand that 'self' is just a convention. So, why is any argument needed at all? Do functions behave differently when they are called from within a class?
Also, and this is almost more important, why does my class work without the benefit of using init ? What would using init do for my class?
Basically, if someone has the time to explain this to me like i'm a 6 year-old, it would help. Thanks in advance for any help.
Defining a function in a class definition invokes some magic that turns it into a method descriptor. When you access foo.method it will automatically create a bound method and pass the object instance as the first parameter. You can avoid this by using the #staticmethod decorator.
__init__ is simply a method called when your class is created to do optional setup. __new__ is what actually creates the object.
Here are some examples
>>> class Foo(object):
def bar(*args, **kwargs):
print args, kwargs
>>> foo = Foo()
>>> foo.bar
<bound method Foo.bar of <__main__.Foo object at 0x01C9FEB0>>
>>> Foo.bar
<unbound method Foo.bar>
>>> foo.bar()
(<__main__.Foo object at 0x01C9FEB0>,) {}
>>> Foo.bar()
Traceback (most recent call last):
File "<pyshell#29>", line 1, in <module>
Foo.bar()
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
>>> Foo.bar(foo)
(<__main__.Foo object at 0x01C9FEB0>,) {}
So, why is any argument needed at all?
To access attributes on the current instance of the class.
Say you have a class with two methods, load_deck and shuffle. At the end of load_deck you want to shuffle the deck (by calling the shuffle method)
In Python you'd do something like this:
class Game(object):
def shuffle(self, deck):
return random.shuffle(deck)
def load_deck(self):
# ...
return self.shuffle(full_deck)
Compare this to the roughly-equivalent C++ code:
class Game {
shuffle(deck) {
return random.shuffle(deck);
}
load_deck() {
// ...
return shuffle(full_deck)
}
}
On shuffle(full_deck) line, first it looks for a local variable called shuffle - this doesn't exist, to next it checks one level higher, and finds an instance-method called shuffle (if this doesn't exist, it would check for a global variable with the right name)
This is okay, but it's not clear if shuffle refers to some local variable, or the instance method. To address this ambiguity, instance-methods or instance-attributes can also be accessed via this:
...
load_deck() {
// ...
return this->shuffle(full_deck)
}
this is almost identical to Python's self, except it's not passed as an argument.
Why is it useful to have self as an argument useful? The FAQ lists several good reasons - these can be summarised by a line in "The Zen of Python":
Explicit is better than implicit.
This is backed up by a post in The History of Python blog,
I decided to give up on the idea of implicit references to instance variables. Languages like C++ let you write this->foo to explicitly reference the instance variable foo (in case there’s a separate local variable foo). Thus, I decided to make such explicit references the only way to reference instance variables. In addition, I decided that rather than making the current object ("this") a special keyword, I would simply make "this" (or its equivalent) the first named argument to a method. Instance variables would just always be referenced as attributes of that argument.
With explicit references, there is no need to have a special syntax for method definitions nor do you have to worry about complicated semantics concerning variable lookup. Instead, one simply defines a function whose first argument corresponds to the instance, which by convention is named "self."
If you don't intent to use self you should probably declare the method to be a staticmethod.
class Game:
#staticmethod
def load_deck():
....
This undoes the automatic default packing that ordinarily happens to turn a function in a class scope into a method taking the instance as an argument.
Passing arguments you don't use is disconcerting to others trying to read your code.
Most classes have members. Yours doesn't, so all of its methods should be static. As your project develops, you will probably find data that should be accessible to all of the functions in it, and you will put those in self, and pass it around to all of them.
In this context, where the application itself is your primary object, __init__ is just the function that would initialize all of those shared values.
This is the first step toward an object-oriented style, wherein smaller pieces of data get used as objects themselves. But this is a normal stage in moving from straight scripting to OO programming.

Categories