This question already has answers here:
Python - default value in class method and <code>self</code>
(2 answers)
Closed 3 years ago.
Context
I'm using vscode. And just running script with all the project files in same folder worked fine. It is as below
MainModule
-aFile.py
-bFile.py
-cFile.py
-dFile.py
While working on my project, I decided that it should be better to separate project into two modules.
MainModule
/subModule00
-aFile.py
-bFile.py
/subModule01
-cFile.py
-dFile.py
After that, I needed to test cFile which imports class from aFile. Running it as script caused an error. So I ran cFile as module and it fixed the import error. But a new error rose.
Question
class ExampleClass(ClassFromAfile):
EXAMPLE_CONSTANT = 1000
def __init__(self, someArg0, someArg1):
self.someVar = someArg0
def exmapleMethod(self, someArg2, someArg3=1000, someArg=self.EXAMPLE_CONSTANT):
# ... so on
While debugging below error occurred while defining exampleMehod
name 'self' is not defined
self is not a reserved keyword in Python.
The first argument of a function in a class is the class instance, thus making it a method of the class. [Unless it is a static method (#staticmethod) or class method, in which case the first argument is the class itself (#classmethod) ]
In your example, you want to initialize someArg as a constant EXAMPLE_CONSTANT.
Then you can simply use as below:
class ExampleClass(ClassFromAfile):
EXAMPLE_CONSTANT = 1000
def __init__(self, someArg0, someArg1):
self.someVar = someArg0
def exmapleMethod(self, someArg2, someArg3=1000, someArg=EXAMPLE_CONSTANT):
# ... so on
To make it clear you can do the following:
In [1]: class Test:
...: def test(t_self, a): # not using self and its good still
...: print(a)
...: def best(b):
...: print(b) # This will print out the class instance itself.
...:
In [2]: te = Test()
In [3]: te.best()
<__main__.Test object at 0x7efc1294b278>
In [24]: te.test(1)
In exampleMethod, self is used in someArg = self.EXAMPLE_CONSTANT. You should add self back to EXAMPLE_CONSTANT for it to work properly or remove self. from your parameter.
Both def and class are executable statements in Python, with the usual scoping and execution time rules. In this case, that means the self in the argument list doesn't exist when the def for the method is run. The default argument value expression self.EXAMPLE_CONSTANT gets evaluated when the def statement runs, and at that time self doesn't exist because the method hasn't been called, and ExampleClass doesn't exist because the class block has not finished (both def and class build an object, callable or class respectively, and assign it to a name). Note that this implies that while def defines a callable that is deferred until it is called, class actually executes everything inside; there are no variable or type declarations like in e.g. C++.
The def for the method runs with its local scope within the class block, so you could use a local reference to values that will be class members:
class Foo:
bar=123
def hmm(self, arg=bar):
return arg
There's also a common workaround for when you need a default argument to be evaluated during a call, rather than at def time:
def append(someitem, somelist=None):
if somelist is None:
somelist = list()
somelist.append(someitem)
return somelist # Caller needs this if we made a new list
Related
This question already has answers here:
Defining private module functions in python
(11 answers)
Closed last year.
for example i have myClassFile.py file with code as follow:
class myClass:
def first(self):
return 'tea'
def second(self):
print(f'drink {self.first()}')
then i have run.py file with code as follow:
from myClassFile import myClass
class_ = myClass()
class_.second()
which when i run will output
>>> 'drink tea'
how to prevent someone to write below code on run.py file or outside myClass ?
class_.first()
so that if they used that method outside myClass class it will be an error or some sort
You can add a level of protection around methods and attributes by prefixing them with __.
But you can't make them totally private (as far as I know), there's always a way around, as shown in example below.
class MyClass:
def __init__(self):
self.__a = 1
def __method(self):
return 2
obj = MyClass()
# obj.__a # raise an exception
# obj.__method() # raise an exception
print(dir(obj)) # you can see the method and attributes have been renamed !
print(obj._MyClass__a) # 1
print(obj._MyClass__method()) # 2
Python does not have support for these. You can mark them private by prefixing them with _, or make it harder to call them by prefixing them with __.
These are called private methods. To make a private variable or a method in python, just prefix it with a __, so def second(self) turns into def __second(self).
This also works for variables and functional programming variables!
class Test:
def test(self):
self.__test()
def __test(self):
print('_test')
x = Test()
x.__test()
gives an error, but x.test() prints _test out successfully!
Note, this can still be run by using x.__Test__test()
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 question already has answers here:
How can I call a function within a class?
(2 answers)
Closed 6 months ago.
How can i call a private function from some other function within the same class?
class Foo:
def __bar(arg):
#do something
def baz(self, arg):
#want to call __bar
Right now, when i do this:
__bar(val)
from baz(), i get this:
NameError: global name '_Foo__createCodeBehind' is not defined
Can someone tell me what the reason of the error is?
Also, how can i call a private function from another private function?
There is no implicit this-> in Python like you have in C/C++ etc. You have to call it on self.
class Foo:
def __bar(self, arg):
#do something
def baz(self, arg):
self.__bar(arg)
These methods are not really private though. When you start a method name with two underscores Python does some name mangling to make it "private" and that's all it does, it does not enforce anything like other languages do. If you define __bar on Foo, it is still accesible from outside of the object through Foo._Foo__bar. E.g., one can do this:
f = Foo()
f._Foo__bar('a')
This explains the "odd" identifier in the error message you got as well.
You can find it here in the docs.
__bar is "private" (in the sense that its name has been mangled), but it's still a method of Foo, so you have to reference it via self and pass self to it. Just calling it with a bare __bar() won't work; you have to call it like so: self.__bar(). So...
>>> class Foo(object):
... def __bar(self, arg):
... print '__bar called with arg ' + arg
... def baz(self, arg):
... self.__bar(arg)
...
>>> f = Foo()
>>> f.baz('a')
__bar called with arg a
You can access self.__bar anywhere within your Foo definition, but once you're outside the definition, you have to use foo_object._Foo__bar(). This helps avoid namespace collisions in the context of class inheritance.
If that's not why you're using this feature, you might reconsider using it. The convention for creating "private" variables and methods in Python is to prepend an underscore to the name. This has no syntactic significance, but it conveys to users of your code that the variable or method is part of implementation details that may change.
This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Closed 6 months ago.
Suppose I have this code:
class Num:
def __init__(self,num):
self.n = num
def getn(self):
return self.n
def getone():
return 1
myObj = Num(3)
print(myObj.getn()) # result: 3
But if I try print(myObj.getone()), I get an error: 'getone()' takes no arguments (1 given).
So I replace:
def getone():
return 1
with
def getone(self):
return 1
Now print(myObj.getone()) shows 1, as expected. But - getone() doesn't need any arguments in order to just return 1. Do I have to use a meaningless argument?
In Python:
Instance methods: require the self argument.
Class methods: take the class as a first argument.
Static methods: do not require either the instance (self) or the class (cls) argument.
__init__ is a special function and without overriding __new__ it will always be given the instance of the class as its first argument.
An example using the builtin classmethod and staticmethod decorators:
import sys
class Num:
max = sys.maxint
def __init__(self,num):
self.n = num
def getn(self):
return self.n
#staticmethod
def getone():
return 1
#classmethod
def getmax(cls):
return cls.max
myObj = Num(3)
# with the appropriate decorator these should work fine
myObj.getone()
myObj.getmax()
myObj.getn()
That said, I would try to use #classmethod/#staticmethod sparingly. If you find yourself creating objects that consist of nothing but staticmethods the more pythonic thing to do would be to create a new module of related functions.
Every method needs to accept one argument: The instance itself (or the class if it is a static method).
Read more about classes in Python.
The fact that your method does not use the self argument (which is a reference to the instance that the method is attached to) doesn't mean you can leave it out. It always has to be there, because Python is always going to try to pass it in.
In python you must always pass in at least one argument to class methods, the argument is self and it is not meaningless its a reference to the instance itself
The current object is explicitly passed to the method as the first parameter. self is the conventional name. You can call it anything you want but it is strongly advised that you stick with this convention to avoid confusion.
If you print(type(Num.getone)) you will get <class 'function'>.
It is just a plain function, and be called as usual (with no arguments):
Num.getone() # returns 1 as expected
but if you print print(type(myObj.getone)) you will get <class 'method'>.
So when you call getone() from an instance of the class, Python automatically "transforms" the function defined in a class into a method.
An instance method requires the first argument to be the instance object. You can think myObj.getone() as syntactic sugar for
Num.getone(myObj) # this explains the Error 'getone()' takes no arguments (1 given).
For example:
class Num:
def __init__(self,num):
self.n = num
def getid(self):
return id(self)
myObj=Num(3)
Now if you
print(id(myObj) == myObj.getid())
# returns True
As you can see self and myObj are the same object