I am trying to write tests for class methods but when I call them I get an AttributeError which complains the methods don't exist.
class Foo:
#staticmethod
def __method_to_test(x)
return x ** 2
Foo.__method_to_test(3)
The last line results in the following: AttributeError: type object 'Foo' has no attribute '__method_to_test'
Why can't I call the method?
Thanks to Sven Eberth, collecting their responses here.
Python Renames Methods That Start With A Double Underline
Starting a method with a double underline causes python to do something called name mangling which causes the method to be renamed from __method_to_test to _Foo__method_to_test.
Call the function like this:
Foo._Foo__method_to_test(3)
Related
I am new to ML and pandas.
I was going through a jupyter file of a linear regression program.
There I saw
dataframe.head()
dataframe.describe()
dataframe.shape
Why does the first two have parentheses () and shape doesn't?
I try to run dataframe.shape() and it give error TypeError: 'tuple' object is not callable.
Here's a link to the documentation but it didn't help:
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.shape.html
dataframe.shape looks like a function and functions should have ().
How to know when a function will not have a ()
Classes can have attributes and methods, attributes are .word, while methods are .word(), or .word(arg1, arg2, etc.)
You won't know in advance whether something you want to call is a method or attribute, but you will if you read the documentation for that class. In that documentation, shape is listed under attributes not under methods, so you can infer from that classification how to use it (i.e. without parentheses). Here's the doc link for pandas dataframes: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html
Make a habit of reading the documentation and it will save you a lot of headache!
This is a Python question and not limited to Pandas. Python uses parentheses as syntactic sugar to "call" the object you initiated the parentheses after.
Suppose you have some object a (this doesn't have to be a function, though functions ARE callable). Then we "call" a by putting parentheses after it.
a()
If a is "callable" it will do something. Otherwise, you'll get an error.
I'll define a stripped down class and show what happens:
class A():
pass
a = A()
a()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-353-d08e164f0b26> in <module>
3
4 a = A()
----> 5 a()
TypeError: 'A' object is not callable
However, I can make a callable by defining a method __call__
class A():
def __call__(self):
return "Hello World!"
a = A()
a()
'Hello World!'
So to answer your question, df.shape doesn't have a __call__ method. This is common for most attributes of class instances and is definitely true for df.shape.
I heard that using getter and setter functions such as set_value() and get_value() isn't Pythonic, and it is always better to use a property object with a setter and getter.
I ran the code below, and I get an error 'str' object is not callable'. When I search for this error, I find many examples of code where the class have an attribute and a method with the same name (like if I write self.name instead of self.__name in the __init__ method).
But I have used two underscores before the attribute - so it shouldn't have happened here. It looks like when I try to call name.setter I actually call a property, and receive back the string stored in self.__name - and it is to this string I then tried to call something else.
But why? In all examples of setter, they have the same name as property and it doesn't lead to problem. Why does it throw an error here, and how do I fix it?
class Dog():
def __init__(self, name):
self.__name = name
#property
def name(self):
return self.__name
#name.setter
def name(self, name_in):
self.__name = name_in
dog = Dog("Barbos")
print(dog.name) # this works
dog.name("Juchka") # and this throws an error:
# TypeError: 'str' object is not callable
You are still thinking in terms of methods here. A setter is not directly called. Instead, a setter is called when you assign to the name.
Use assignment:
dog.name = "Juchka"
Python translates this into a call to the setter method.
Just accessing dog.name calls the getter, and the getter method returned a string. Calling is a separate expression from looking up the object to apply the call to; dog.name("Juchka") first executes dog.name, and applies the ("Juchka") call expression to the result of that attribute lookup. The attribute lookup returned "Barbos", and "Barbos"("Juchka") indeed does not work.
Demo:
>>> dog = Dog("Barbos")
>>> dog.name
'Barbos'
>>> 'Barbos'("Juchka") # what really happens when you try to call dog.name(...)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>> dog.name = "Juchka"
>>> dog.name
'Juchka'
This is inspired by a question I just saw, "Change what is returned by calling class instance", but was quickly answered with __repr__ (and accepted, so the questioner did not actually intend to call the instance).
Now calling an instance of a class can be done like this:
instance_of_object = object()
instance_of_object()
but we'll get an error, something like TypeError: 'object' object is not callable.
This behavior is defined in the CPython source here.
So to ensure we have this question on Stackoverflow:
How do you actually call an instance of a class in Python?
You call an instance of a class as in the following:
o = object() # create our instance
o() # call the instance
But this will typically give us an error.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'object' object is not callable
How can we call the instance as intended, and perhaps get something useful out of it?
We have to implement Python special method, __call__!
class Knight(object):
def __call__(self, foo, bar, baz=None):
print(foo)
print(bar)
print(bar)
print(bar)
print(baz)
Instantiate the class:
a_knight = Knight()
Now we can call the class instance:
a_knight('ni!', 'ichi', 'pitang-zoom-boing!')
which prints:
ni!
ichi
ichi
ichi
pitang-zoom-boing!
And we have now actually, and successfully, called an instance of the class!
The short answer is that the object class has no __call__ method (you can check that with "dir(object)"). When you create an instance of a class the __init__ method is called and when you call the instance, the __call__ method is called.
Up Votes for Everyone!
Thanks for posting the question and thanks for answering.
I thought I would just share my implementation in case that helps others ...
I have a class (called RTS) and it contains an SQL Query that I access using a 'get'. The class works fine as an independent endpoint. Now I want to call that class from within the program.
Using the answer above I added the following:
class RTS(Resource):
def __call__(self):
print("In RTS")
def get(self, user_id):
try: ...
In order to call the class from elsewhere in the program I added:
getGR = RTS.get(self, user_unique_id)
Voila - I got the same info I could check on Postman returned within the program.
I was just looking at one question here and the OP was using a same name for class, other things and also for variable. When I was trying to answer it, I became confused myself and thus thought of asking.
For example:
class MyClass:
pass
MyClass=MyClass()
Though, I will never code anything like this. I would like to understand how this will be treated by python interpreter. So my question is, is the variable MyClass I will use will be created first or the other way? Which is, creating an instance of MyClass firstly and assigning it to MyClass variable. I think the latter is correct but if that is the case, how will the following be resolved?
class MyClass:
pass
MyClass=MyClass()
new_class=MyClass()
The right-hand side of the assignment is processed first, so an instance of MyClass is created. But then you reassign the name MyClass to that instance. When you execute
new_class = MyClass()
you should get an error about MyClass not being callable, since that name now refers to an instance of the original class, not the class itself.
class MyClass:
pass
MyClass=MyClass()
In simple terms, the above code does three things (in this order):
Defines the class MyClass.
Creates an instance of MyClass.
Assigns that instance to the variable MyClass.
After the last step, the class MyClass is overwritten and can no longer be used. All you have left is an instance of it contained in the variable MyClass.
Moreover, if you try to call this instance as you would a class, you will get an error:
>>> class MyClass:
... pass
...
>>> MyClass=MyClass()
>>> new_class=MyClass()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'MyClass' object is not callable
>>>
The line:
new_class=MyClass()
in most cases will return an error, saying something like instance not callable.
MyClass now refers to the instance of what MyClass previous held that is a class.
You could make a new instance of former MyClass by:
new_class = MyClass.__class__()
MyClass is just just a variable that points/refers to a particular object. First it was class then it was changed to hold an instance of that class.
Variables are treated as objects in Python. From my understanding, when you assign a new instance of MyClass to an object, python will try to create a reference of the original class to the object and duplicate. However, the namespace of the new object is already used (in the original MyClass), and the duplication will return you an error, so the first code will not work.
For the second piece of code, the final line will not execute due to the same reason of Namespace Duplication. Since the last but one line failed, the proposed reference target is still the original MyClass, which won't work at all.
I tried to subclass threading.Condition earlier today but it didn't work out. Here is the output of the Python interpreter when I try to subclass the threading.Condition class:
>>> import threading
>>> class ThisWontWork(threading.Condition):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
function() argument 1 must be code, not str
Can someone explain this error? Thanks!
You're getting that exception because, despite its class-like name, threading.Condition is a function, and you cannot subclass functions.
>>> type(threading.Condition)
<type 'function'>
This not-very-helpful error message has been raised on the Python bugtracker, but it has been marked "won't fix."
Different problem than OP had, but you can also get this error if you try to subclass from a module instead of a class (e.g. you try to inherit My.Module instead of My.Module.Class). Kudos to this post for helping me figure this out.
TypeError: Error when calling the metaclass bases
For this one, the answer is that you probably named a python class the
same thing as the module (i.e., the file) that it's in. You then
imported the module and attempted to use it like a class. You did this
because you, like me, were probably a Java programmer not that long
ago :-). The way to fix it is to import the module.class instead of
just the module. Or, for sanity's sake, change the name of the class
or the module so that it's more obvious what's being imported.
With respect to subclassing a module, this is a really easy mistake to make if you have, for example, class Foo defined in a file Foo.py.
When you create a subclass of Foo in a different file, you might accidentally do the following (this is an attempt to subclass a module and will result in an error):
import Foo
class SubclassOfFoo(Foo):
when you really need to do either:
from Foo import Foo
class SubclassOfFoo(Foo):
or:
import Foo
class SubclassofFoo(Foo.Foo):
Gotten into the same problem. Finally solved by taking a keen look at the code and this is where the TypeError that alarms about a string instead of code comes about..
Class Class_name(models.model): //(gives a TypeError of 'str' type)
"And"
Class Class_name(models.Model): // is the correct one.
Notice that specific error comes about because of a single lowercase letter to the code "Model" which in turn makes it a string