I am using pypy to translate some python script to C language.
Say that I have a python class like this:
class A:
def __init__(self):
self.a = 0
def func(self):
pass
I notice that A.func is a unbound method rather than a function so that it cannot be translated by pypy. So I change the code slightly:
def func(self):
pass
class A:
def __init__(self):
self.a = 0
A.func = func
def target(*args):
return func, None
Now func seems to be able to be translated by pypy. However when I try translate.py --source test.py, an exception [translation:ERROR] TypeError: signature mismatch: func() takes exactly 2 arguments (1 given) is raised. I notice that it might because I haven't annotate self argument yet. However this self have type A, so how can I annotate a class?
Thank you for your reading and answer.
Essentially PyPy's entry point is a function (accepting sys.argv usually as an argument). Whatever this function calls (create objects, call methods) will get annotated. There is no way to annotate a class, since PyPy's compiled code does not export this as API, but rather as a standalone program.
You might want to for example:
def f():
a = A()
a.func()
or even:
a = A()
def f():
a.func()
in which case a is a prebuilt constant.
Are you wanting a staticmethod or a classmethod?
Related
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)
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()
This is my code:
class bla:
def function1():
print 1
def function2():
bla.function1()
x = bla()
x.function2()
I don't understand why I get the error "TypeError: function2() takes no arguments (1 given)" as I don't seem to be passing any argument to function2.
Regular methods are called with an implicit self reference to their object - otherwise they wouldn't be able to access any data members of x.
They should always be declared like so:
class bla:
def function1(self):
print 1
if you want them to operate on the object (self is loosely equivalent to the this pointer in C++, for example).
Alternatively, if you don't care about the object (so you're really just using the class to group some functions together), you can make them static like so:
class bla:
#staticmethod
def function1():
print 1
#staticmethod
def function2():
bla.function1()
In fact, that's the only way you can call bla.function1() without an instance of bla from your function2.
That's cause your calling your function as a method and that automatically binds the method's object as the first argument to your function.
Either do:
bla.function2() #a function call
or:
class bla:
#normal and correct way to define class methods - first argument is the object on which the method was called
def function1(self):
print 1
def function2(self):
self.function1()
You have to type:
class bla:
def function1(self):
print 1
def function2(self):
self.function1()
self (a reference to the object on which the method is called) is passed as the first parameter to each method. The name of this first variable, "self" is just a common convention.
You have to pass the argument self to the functions function1 and function2. See the Python Classes documentation. So your code would be
class Bla: # Notice capitalization.
def function1(self):
print 1
def function2(self):
bla.function1()
x = Bla()
x.function2()
See also the answers to the question Why do you need explicitly have the “self” argument into a Python method?.
Basically in Python a call to a member function (like function1)
x = Bla()
x.function1()
is translated into
Bla.function(x)
self is used to refer to the instance of the class x.
Really sorry for the extremely stupid title, but if I know what it is, I wouldn't write here (:
def some_decorator( func ):
# ..
class A:
#some_decorator
def func():
pass
#func.some_decorator # this one here - func.some_decorator ?
def func():
pass
some_decorator decorates func - that's OK. But what is func.some_decorator and how some_decorator becomes a member ( or something else ? ) of func?
P.S. I'm 90% sure, that there's such question here (as this seems something basic), but I don't know how to search it. If there's a exact duplicate, I'll delete this question.
Note : It's not typo, nor accident, that both member functions are named func. The decorator is for overloading: the question is related to Decorating method (class methods overloading)
Remember that the function definition with decorator is equivalent to this:
def func():
pass
func = some_decorator(func)
So in the following lines, func doesn't refer to the function you defined but to what the decorator turned it into. Also note that decorators can return any object, not just functions. So some_decorator returns an object with a method (it's unfortunate that the names some_decorator and func are reused in the example - it's confusing, but doesn't change anything about the concept) that is itself a decorator. As the expression after the # is evaluated first, you still have a reference to the first decorator's method after you defined another plain function func. That decorator is applied to this new function. The full example is then equivalent to this:
class A:
def func():
pass
func = some_decorator(func)
_decorator = func.some_decorator
def func():
pass
func = _decorator(func)
One way to clarify this is to demonstrate it with a concrete example that behaves like this, the builtin property descriptor:
class C(object):
#property
def x(self):
"This is a property object, not a function"
return self._x
#x.setter
def x(self, val):
self._x = val
>>> c = C()
>>> c.x = 1
>>> c.x
1
>>> C.x
<property object at 0x2396100>
>>> C.x.__doc__
'This is a property object, not a function'
>>> C.x.getter.__doc__
'Descriptor to change the getter on a property.'
>>> C.x.setter.__doc__
'Descriptor to change the setter on a property.'
>>> C.x.deleter.__doc__
'Descriptor to change the deleter on a property.'
The first invocation of property (as a decorator) means that x is not a function - it is a property descriptor. A feature of properties is that they allow you to initially define just the fget method, and then provide fset and fdel later by using the property.setter and property.deleter decorators (although since each of these creates a new property object, you do need to make sure to use the same name each time).
Something similar will usually be the case whenever you see code using this kind of pattern. Ideally, the naming of the decorators involved will make it reasonably clear what is going on (e.g. most people seem to grasp the idiom for defining property attributes reasonably easily).
As far as I know, self is just a very powerful convention and it's not really a reserved keyword in Python. Java and C# have this as a keyword. I really find it weird that they didn't make a reserved keyword for it in Python. Is there any reason behind this?
Because self is just a parameter to a function, like any other parameter. For example, the following call:
a = A()
a.x()
essentially gets converted to:
a = A()
A.x(a)
Not making self a reserved word has had the fortunate result as well that for class methods, you can rename the first parameter to something else (normally cls). And of course for static methods, the first parameter has no relationship to the instance it is called on e.g.:
class A:
def method(self):
pass
#classmethod
def class_method(cls):
pass
#staticmethod
def static_method():
pass
class B(A):
pass
b = B()
b.method() # self is b
b.class_method() # cls is B
b.static_method() # no parameter passed
Guido van Rossum has blogged on why explicit self has to stay: http://neopythonic.blogspot.com/2008/10/why-explicit-self-has-to-stay.html
I believe that post provides some insight into the design decisions behind explicit self.
Because a method is just a function who's first parameter is used to pass the object. You can write a method like this:
class Foo(object):
pass
def setx(self, x):
self.x = x
Foo.setx = setx
foo = Foo()
foo.setx(42)
print foo.x # Prints 42.
Whatever the merit or otherwise of this philosophy, it does result in a more unified notion of functions and methods.