Python, a function in a method - python

I have a method (__init__) in a class, and I want to use a function from the class in this method.
But when I want to run my program. I get: NameError: global name 'myfunction' is not defined
Someone, who knows what I have to do? :)
Thank you. But I have still a problem, because def myFunc(self, a): is a method and I wanted a function.

class Myclass(object):
def __init__(self, a):
self.a = self.myFunc(a)
def myFunc(self, a):
return a+1

Then you don't have a function call in the method, but you have a method call in it.
When creating a class you must specify the object when calling its methods:
>>> class A(object):
... def __init__(self, val):
... self.val = self._process(val)
... def _process(self, val):
... return val % 7
... process = _process #if you are outside methods then you don't
... #have to add "self.".
...
>>> a = A(5)
>>> a.process(3)
3
>>> a._process(6) #"a" is passed as the "self" parameter
6
As you can see in a class definition, but outside the methods you must specify the method name only, and not the "self.". Also you can't refer to a method not already defined:
>>> class B(object):
... def __init__(self):pass
... def method1(self):pass
... __call__ = method2 #method2 not defined!
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in B
NameError: name 'method2' is not defined

Related

Does the #staticmethod decorator do anything?

I made these two classes:
class A:
#staticmethod
def f(x):
print("x is", x)
class B:
def f(x):
print("x is", x)
And used them like this:
>>> A.f(1)
x is 1
>>> B.f(1)
x is 1
It looks like f became a static method on B even without the decorator. Why would I need the decorator?
It used to matter more back in Python 2, where the instance-ness of instance methods was enforced more strongly:
>>> class B:
... def f(x):
... print("x is", x)
...
>>> B.f(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method f() must be called with B instance as first argument (
got int instance instead)
You had to mark static methods with #staticmethod back then.
These days, #staticmethod still makes it clearer that the method is static, which helps with code readability and documentation generation, and it lets you call the method on instances without the system trying to bind self.
Try these two classes, both having a cry method, one as a classmethod and another as a staticmethod with self passed on
class Cat:
def __init__(self):
self.sound = "meow"
def cry(self):
print(self.sound)
x = Cat()
x.cry()
meow
and with another class
class Dog:
def __init__(self):
self.sound = "ruff-ruff"
#staticmethod
def cry(self):
print(self.sound)
x = Dog()
x.cry()
TypeError: cry() missing 1 required positional argument: 'self'
and we can see the #staticmethod decorator basically removed the passed in self

Access static class variable in instance method

Say I have class Test defined as this:
class Test
test_var = 2
def test_func():
print(test_var)
I can find out what test_var is fine like so:
>>> Test.test_var
2
...But calling Test.test_func() does not work.
>>> Test.test_func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in test
NameError: name 'test_var' is not defined
If I change Test.test_func() like this (note that this is pseudo-code):
redef test_func():
print(Test.test_var)
It works fine:
>>> Test.test_func()
2
...and that makes sense. But how can I make the first example work, keeping in mind that I want test_func to be an instance method?
Note that the code posted above is example code, and so typos should be ignored.
You can always access class-level attributes via the instance, ie self, as long as you have not shadowed them with an instance attribute of the same name. So:
def test_func(self):
print(self.test_var)
In your example, test_func is just a function and although its defined in the class namespace, the function itself doesn't know about the class namespace. You want either a regular instance method or a class method.
class Test:
test_var = 2
def instance_test(self):
# instance methods will look in self first and class namespace second
print(self.test_var)
#classmethod
def class_test(cls):
# class methods take the class itself as first argument
print(cls.test_var)
t = Test()
t.instance_test()
Test.class_test()
You need to either pass self (almost always what you want) to the class method or add a #classmethod or #staticmethod decorator if you don't need self. Then create an instance of the class and call the test_func method.
Examples:
# test_var is an class variable and test_func has a classmethod decorator
>>> class Test:
... test_var = 2
... #classmethod
... def test_func(cls):
... print(cls.test_var)
...
>>> t = Test()
>>> t.test_func()
2
# test_var is an class variable and test_func has a staticmethod decorator
>>> class Test:
... test_var = 2
... #staticmethod
... def test_func():
... print(Test.test_var)
...
>>> t = Test()
>>> t.test_func()
2
# test_var is an instance variable here
>>> class Test:
... self.test_var = 2
... def test_func(self):
... print(self.test_var)
...
>>> t = Test()
>>> t.test_func()
2

Accessing attribute from parent class inside child class

When I access an attribute from the parent class via the child class like this all works fine:
class A():
a=1
b=2
class B(A):
c=3
d=B.a+B.b+B.c
print d
But if I try to access an attribute from the parent class inside the child class like this, it doesn't work:
class A():
a=1
b=2
class B(A):
c=3
d=a+b+c
print d
I receive the error: name 'a' is not defined
Let assume that I have many equation like d=a+b+c (but more complicated) and I can't edit them - I have to call in class B "a" as "a", not "self.a" or "something.a". But I can, before equations, do A.a=a. But it is not the smartest way to reload all variables manually. I want to bypass it using inheritance. Is it possible or i should do all manually? Or maybe it is 3th route in this code?
During the class definition, none of the inherited attributes are available:
>>> class Super(object):
class_attribute = None
def instance_method(self):
pass
>>> class Sub(Super):
foo = class_attribute
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
class Sub(Super):
File "<pyshell#7>", line 2, in Sub
foo = class_attribute
NameError: name 'class_attribute' is not defined
>>> class Sub(Super):
foo = instance_method
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
class Sub(Super):
File "<pyshell#9>", line 2, in Sub
foo = instance_method
NameError: name 'instance_method' is not defined
You can't even access them using super, as the name of the subclass isn't defined within the definition block*:
>>> class Sub(Super):
foo = super(Sub).instance_method
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
class Sub(Super):
File "<pyshell#11>", line 2, in Sub
foo = super(Sub).instance_method
NameError: name 'Sub' is not defined
The only way to access the inherited attributes at definition time is to do so explicitly, using the name of the superclass:
>>> class Sub(Super):
foo = Super.class_attribute
>>> Sub.foo is Super.class_attribute
True
Alternatively you can access them within class or instance methods, but then you need to use the appropriate prefix of the class (conventionally cls) or instance (conventionally self) parameter.
* for anyone thinking "ah, but in 3.x you don't need arguments to super":
>>> class Sub(Super):
foo = super().instance_method
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
class Sub(Super):
File "<pyshell#6>", line 2, in Sub
foo = super().instance_method
RuntimeError: super(): no arguments
That's only true inside instance/class methods!
I may be wrong on this, but are you sure you don't want rather this?
class A(object):
def __init__(self):
self.a = 1
self.b = 2
class B(A):
def __init__(self):
super(B, self).__init__()
self.c = 3
#property
def d(self):
return self.a + self.b + self.c
BB = B()
print BB.d
or, as jonrsharpe pointed out:
class A():
a=1
b=2
class B(A):
c=3
d=A.a+A.b+c
print B.d

Accessing variable and functions in object oriented python - python

How to I declare a default value in a python object?
Without a python object it looks fine:
def obj(x={123:'a',456:'b'}):
return x
fb = obj()
print fb
With a python object I get the following error:
def foobar():
def __init__(self,x={123:'a',456:'b'}):
self.x = x
def getStuff(self,field):
return x[field]
fb = foobar()
print fb.x
Traceback (most recent call last):
File "testclass.py", line 9, in <module>
print fb.x
AttributeError: 'NoneType' object has no attribute 'x'
How do I get the object to return the value of a variable in the object?
With a python object, I got an error:
def foobar():
def __init__(self,x={123:'a',456:'b'}):
self.x = x
def getStuff(self,field):
return x[field]
fb2 = foobar({678:'c'})
print fb2.getStuff(678)
Traceback (most recent call last):
File "testclass.py", line 8, in <module>
fb2 = foobar({678:'c'})
TypeError: foobar() takes no arguments (1 given)
You didn't define a class, you defined a function with nested functions.
def foobar():
def __init__(self,x={123:'a',456:'b'}):
self.x = x
def getStuff(self,field):
return x[field]
Use class to define a class instead:
class foobar:
def __init__(self,x={123:'a',456:'b'}):
self.x = x
def getStuff(self, field):
return self.x[field]
Note that you need to refer to self.x in getStuff().
Demo:
>>> class foobar:
... def __init__(self,x={123:'a',456:'b'}):
... self.x = x
... def getStuff(self, field):
... return self.x[field]
...
>>> fb = foobar()
>>> print fb.x
{456: 'b', 123: 'a'}
Do note that using a mutable value for a function keyword argument default is generally not a good idea. Function arguments are defined once, and can lead to unexpected errors, as now all your classes share the same dictionary.
See "Least Astonishment" and the Mutable Default Argument.
to define a class in python you have to use
class classname(parentclass):
def __init__():
<insert code>
With your code you're declaring a method not a class
Use
class foobar:
instead of
def foobar():

Getting NameError when calling function in constructor

I ran the code below, by calling the function in the constructor
First --
>>> class PrintName:
... def __init__(self, value):
... self._value = value
... printName(self._value)
... def printName(self, value):
... for c in value:
... print c
...
>>> o = PrintName('Chaitanya')
C
h
a
i
t
a
n
y
a
Once again I run this and I get this
>>> class PrintName:
... def __init__(self, value):
... self._value = value
... printName(self._value)
... def printName(self, value):
... for c in value:
... print c
...
>>> o = PrintName('Hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
NameError: global name 'printName' is not defined
Can I not call a function in the constructor? and whay a deviation in the execution of similar code?
Note: I forgot to call a function local to the class, by using self (ex: self.printName()). Apologize for the post.
You need to call self.printName since your function is a method belonging to the PrintName class.
Or, since your printname function doesn't need to rely on object state, you could just make it a module level function.
class PrintName:
def __init__(self, value):
self._value = value
printName(self._value)
def printName(value):
for c in value:
print c
Instead of
printName(self._value)
you wanted
self.printName(self._value)
It probably worked the first time because you had another function printName in a parent scope.
What you want is self.printName(self._value) in __init__, not just printName(self._value).
I know this is an old question, but I just wanted to add that you can also call the function using the Class name and passing self as the first argument.
Not sure why you'd want to though, as I think it might make things less clear.
class PrintName:
def __init__(self, value):
self._value = value
PrintName.printName(self, self._value)
def printName(self, value):
for c in value:
print(c)
See Chapter 9 of the python manuals for more info:
9.3.4. Method Objects
Actually, you may have guessed the answer: the special thing about methods is that the object is passed as the first argument of the function. In our example, the call x.f() is exactly equivalent to MyClass.f(x). In general, calling a method with a list of n arguments is equivalent to calling the corresponding function with an argument list that is created by inserting the method’s object before the first argument.

Categories

Resources