I have written a class called cl:
class cl :
def __int__(self):
self.a = 0
def increment(self):
self.a +=1
def print_a(self):
print ("value : "+str(self.a))
I have written another class called test. However, I got an error when calling methods.
from cl import *
class test :
def __int__(self):
self.b = 0
self.c = cl()
def main(self):
self.c.increment()
self.c.print_a()
self.c.increment()
self.c.print_a()
d = test()
d.main()
What I got is this:
Traceback (most recent call last):
File "test_file.py", line 19, in <module>
d.main()
File "test_file.py", line 12, in main
self.c.increment()
AttributeError: test instance has no attribute 'c'
Can anyone explain why that happens and what is the issue with my code? I am a high school student. Can you explain to me? And can you help me to fix this?
You're misspelling __init__ with __int__:
class cl :
def __int__(self):
self.a = 0
Should be
class cl :
def __init__(self):
self.a = 0
Note that encompassing a main method inside of the test class is really an anti-pattern in Python; the form of
def main():
...
if __name__ == "__main__":
main()
is preferred and is more Pythonic.
For some reference on the if __name__ == "__main__" pattern, see:
https://stackoverflow.com/a/419185/1730261
https://docs.python.org/3/library/main.html
main function does not belong the class test , it belongs the test.py which your test class in, so the self in main is test.py , not test
Related
After I ran the code below, I got NameError: name 'result' is not defined. I tried to use class variable in a class method. Why does it give me an error?
class Test():
def __init__(self):
self.a=self.test1()
self.result = Test.test2()+Test.test3()
def test1(self):
a=100
return a
result = Test.test3()+100
#classmethod
def test2(cls):
b=200
return b
#staticmethod
def test3():
print("Testing3 is calling ")
c=500+Test.result
return c
Error:
result = Test.test3()+100
File "<ipython-input-29-29d4025016c1>", line 18, in test3
c=500+result
NameError: name 'result' is not defined
At the time the line of code in question is evaluated, result is not a class variable. It's been defined as an instance variable here:
def __init__(self):
self.a=self.test1()
self.result = Test.test2()+Test.test3()
but the line of code that defines Test.result as a class variable:
result = Test.test3()+100
has not yet finished executing at the time that it calls test3(), which itself has a dependency on Test.result.
Instead of using a global variable, I'm trying to make an instance of a variable in a class, as it seems to be best practice. How do I reference this variable across other functions in the class? I would have thought that Test.running_sum would work or at least running_sum in test_function, but I'm not having any luck with either. Thanks very much!
class Test:
def __init__(self):
self.root = None
running_sum = 0
def test_function(self):
print(Test.running_sum)
return
x = Test()
x.test_function()
Error:
Traceback (most recent call last):
File "so.py", line 1, in <module>
class Test:
File "so.py", line 10, in Test
x = Test()
NameError: name 'Test' is not defined
Use self parameter provided in the method signature.
Note that what you wrote is not a method, but an external function using class Test. To write a method of Test, the def should be at one level of indentation inside class Test as following:
class Test:
def __init__(self):
self.running_sum = 0
def test_function(self):
print(self.running_sum)
There are several things to add if you want an explanation behind this "best practice".
Assuming you write the following code:
class Test:
numbers = []
def add(self, value):
self.numbers.append(value)
The Test.numbers list is instantiated once and shared accross all instances of Test. Therefore, if 2 different instances add to the list, both act on the same list:
a = Test()
b = Test()
a.add(5)
b.add(10)
assert a.numbers == b.numbers == Test.numbers
When creating instance variables in the __init__ function, __init__ will be run at each instantiation, and therefore, the list will no longer be shared because they will be created for each individual instances.
class Test:
def __init__(self):
self.numbers = []
def add(self, number):
self.numbers.append(number)
a = Test()
b = Test()
a.add(5)
b.add(10)
assert a != b
As an object attribute: each object gets its own.
Test is the class; self is the Test object that invoked the method.
class Test:
def __init__(self):
self.root = None
self.running_sum = 0
def test_function(self):
self.running_sum += 1
print(self.running_sum)
return
x = Test()
y = Test()
x.test_function()
y.test_function()
Output:
1
1
As a class attribute: all objects share the same variable.
self.__class__ is the class of the invoking object (i.e. Test).
class Test:
running_sum = 0
def __init__(self):
self.root = None
def test_function(self):
self.__class__.running_sum += 1
print(self.__class__.running_sum)
return
x = Test()
y = Test()
x.test_function()
y.test_function()
Output:
1
2
how do I reference this variable across other functions in the class
Several things I see wrong here. First of all, you are calling running_sum on the class itself which doesn't make sense since you are declaring running_sum as an attribute of an instance of Test. Second, from the way you formatted your question, it seems that test_function is outside of the class Test which doesn't make sense since you are passing self to it, implying it is an instance method. To resolve you could do this:
class Test:
def __init__(self):
self.running_sum = 0
def test_function(self):
print(self.running_sum)
Then again this also is weird... Why would you need a "test_function" when you can simply test the value of running_sum by simply doing:
x = Test()
x.running_sum
In your __init__ function, you've created a local variable. That variable will no longer exist after the function has completed.
If you want to create a variable specific to the object x then you should create a self.running_sum variable
class Test:
def __init__(self):
self.root = None
self.running_sum = 0
def test_function(self):
print(self.running_sum)
If you want to create a variable specific to the class Test then you should create a Test.running_sum variable.
class Test:
running_sum = 0
def __init__(self):
self.root = None
def test_function(self):
print(Test.running_sum)
A derived class has access to its base class member functions implicitly, unless I am mistaken. A derived class can also access its base class' attributes by prefixing a call to them like this: BaseClass.base_attribute. But I seemingly do not understand how instances of a derived class can use the methods of the base class. Example:
class Visitor():
""" Interface to Visitor
provide an interface to visitors that
perform an operation on a data collection """
def visitProduce():
pass
def visitMeat():
pass
def visitBakedGoods():
pass
def visitDairy():
pass
def visitNonFood():
pass
class PriceVisitor(Visitor):
__cost = 0.0 # total cost of groceries
def __init__(self):
self.__cost = 0.0
def visitProduce(self, p):
self.__cost += p.price()
def visitMeat(self, m):
self.__cost += m.price()
def visitBakedGoods(self, b):
self.__cost += b.price()
def visitDairy(self, d):
self.__cost += d.price()
def visitNonFood(self, nf):
self.__cost += nf.price()
class Groceries():
shopping_cart = [] # list of grocery items
def Groceries(self):
self.shopping_cart = []
def addProduce(self, p):
pass
def addMeat(self, m, lb):
pass
def addBakedGoods(self, b):
pass
def addDairy(self, d):
pass
def addNonFood(self, nf):
pass
def accept(self, v):
pass
def getShoppingCart(self):
print(self.shopping_cart)
def calculateCost(self, v):
for item in self.shopping_cart:
item.accept(v)
item.details()
print('Total cost is: $', v.__cost)
class Produce(Groceries):
def addProduce(self):
Groceries.shopping_cart.append(self)
def accept(self, v):
v.visitProduce(self)
def price(self):
return self.__price
def details(self):
print(self.__name, ' for: $', self.__price + '')
class Apples(Produce):
__name = None
__price = 3.25
def __init__(self, name):
self.__name = name
And here is a test of the Apple, Produce, Groceries, and PriceVisitor classes
import VisitorPattern as vp
def main():
# Visitor object
my_visitor = vp.PriceVisitor()
# Grocery object stores objects in its shopping_cart attribute
my_groceries = vp.Groceries()
# Add items
red_apple = vp.Apples('red apple')
gold_apple = vp.Apples('gold apple')
red_apple.addProduce()
gold_apple.addProduce()
my_groceries.getShoppingCart()
my_groceries.calculateCost(my_visitor)
if __name__ == '__main__':
main()
Now, the way I understand it is that upon the construction of the instance of Apple, it has access to Produce's method price(). Calling this method with an instance of the Apple class will then pass its own instance in place of the 'self'. The program then returns the value of the __price attribute belonging to the instance calling the method, in this case Apple. However, I get this error:
C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4>python test.
py
[<VisitorPattern.Apples object at 0x026E0830>, <VisitorPattern.Apples object at
0x026E0910>]
Traceback (most recent call last):
File "test.py", line 23, in <module>
main()
File "test.py", line 20, in main
my_groceries.calculateCost(my_visitor)
File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi
torPattern.py", line 60, in calculateCost
item.accept(v)
File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi
torPattern.py", line 71, in accept
v.visitProduce(self)
File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi
torPattern.py", line 28, in visitProduce
self.__cost += p.price()
File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi
torPattern.py", line 74, in price
return self.__price
AttributeError: 'Apples' object has no attribute '_Produce__price'
How does the binding and namespaces actually work in inheritance? I could just write the price() method in each of Produce's derived classes, but that would defeat the point of inheritance. I think my problem also stems from name mangling, but still don't know what happens if I don't make my attributes 'private'. Clarification would be great. Thanks
Edit
I declared the constructor of Groceries wrong:
# Wrong way
def Groceries(self):
self.shopping_cart = []
# Should be
def __init__(self):
self.__shopping_cart = []
The product of a full time job and homework in the evening
What is the order of namespaces in inheritance?
Python uses the Method Resolution Order to find the method bound to that instance of the object.
It also invokes name mangling, which is why you can't find the method, _Produce__price. You're trying to use .__price but when it is inherited, Python adds the name of the class to the front of the name. Don't use two underscores, change the two underscores to one, and your code will work as you expect, and you'll consistently look up ._price which won't invoke the name mangling.
See the docs for more on this:
https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references
Not really a direct answer to all your questions but I hope the following code sheds some light on how to do inheritance in Python.
class Produce(object):
def __init__(self, name=None, price=None):
self.__name = name
self.__price = price
def __str__(self):
return self.__name
#property
def bulk_price(self):
return self.__price * 100
class Apple(Produce):
def __init__(self, name="Apple"):
self.__name = name
self.__price = 3.25
super(self.__class__, self).__init__(self.__name, self.__price)
a = Apple("Gold Apple")
print a
print a.bulk_price
# Gold Apple
# 325.0
As you can see, I made name and price inaccessible in both classes. This way, I cannot just call them explicitly, i.e. a.__price. By using super as well in the child class, I am able to avoid referring to the base class further while still having access to its methods.
I have saw your error, your parent need to call child's function, but you have not transferred child to parent, so it will get the errors.Now I give my example:
class A:
def __init__(self, handler):
self.a = 5
self.real_handler = handler
def get(self):
print "value a = %d"%self.a
self.real_handler.put()
class B(A):
def __init__(self):
A.__init__(self, self) ##transport B to A
self.b = 3
def get(self):
print "value b is %d"%self.b
A.get(self)
def put(self):
self.b = 6
print "value b change into %d"%self.b
if __name__=="__main__":
b = B()
b.get()
In parent B, it will call the child A's fuction put(). I hope this can help you.
I have a file named main.py which contains a class called mainWindow. I have a second file named popupWindow.py, which contains a class named popupWindow. mainWindow class contains 2 methods. One called clearListBox which clears the list box in the main window, and one called addScouts(I) which is a recursive function for writing the scouts stored in a file to the list box. I would like to be able to call the clearListBox and addScouts(I) from my class popupWindow. How do i achieve this?
upon trying from main import mainWindow then calling mainWindow.addScouts(1) i received the error that addScouts requires arg self
In my main.py file:
class mainWindow:
def __init__(self,master):
self.master = master
self._scouts = []
addBtn = Button(master,text="Create Scout",command=self._createScout)
addBtn.pack()
remBtn = Button(master,text="Remove Scout",command=self._removeScout)
remBtn.pack()
fndBtn = Button(master,text="Find Scout",command=self._findScout)
fndBtn.pack()
exitBtn = Button(master,text="Exit",command=self._exit)
exitBtn.pack()
scoutList = Listbox(master)
scoutList.pack()
self.scoutList = scoutList
self.addScouts(1)
w = 1000 #The value of the width
h = 750 #The value of the height of the window
# get screen width and height
ws = root.winfo_screenwidth()#This value is the width of the screen
hs = root.winfo_screenheight()#This is the height of the screen
# calculate position x, y
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
#This is responsible for setting the dimensions of the screen and where it is
#placed
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
self._createLeaderboard()
def addScouts(self,I):
i = I
with open(fileName,"r") as f:
lines = f.readlines()
for line in lines:
if str(line.split(",")[3])[:-1] == str(i):
self.scoutList.insert(END,line[:-1])
i += 1
return self.addScouts(i)
return
def clearListBox(self):
self.scoutList.delete(0,END)
return
In popupWindow.py:
from main import mainWindow
In popupWindow class:
mainWindow.clearListBox()
mainWindow.addScouts(1)
My Error:
Traceback (most recent call last):
File "C:\Users\KRIS\Documents\Python Projects\Scouts\popupWindow.py", line 4, in <module>
from main import mainWindow
File "C:\Users\KRIS\Documents\Python Projects\Scouts\main.py", line 4, in <module>
from popupWindow import *
File "C:\Users\KRIS\Documents\Python Projects\Scouts\popupWindow.py", line 4, in <module>
from main import mainWindow
ImportError: cannot import name 'mainWindow'
Thank you in advance
This question has been asked times and times again - and is nothing Python-specific. To call a method on an instance of another class, you need to have a reference to this instance. The very obvious solution is to pass this reference, either at call time:
class A(object):
def __init__(self, var_a):
self.var_a = var_a
def method(self, another_object):
return another_object.another_method(self.var_a)
class B(object):
def __init__(self, var_b):
self.var_b = var_b
def another_method(self, var):
return self.var_b + var
a = A(42)
b = B(1138)
print a.method(b)
or at instanciation time:
class A(object):
def __init__(self, var_a, another_object):
self.var_a = var_a
self.another_object = another_object
def method(self):
return self.another_object.another_method(self.var_a)
class B(object):
def __init__(self, var_b):
self.var_b = var_b
def another_method(self, var):
return self.var_b + var
b = b(1138)
a = A(b)
print a.method()
Note that in both cases, B doesn't need to know about class A - it just gets an instance as param and that's it. So if A and B live in different modules, the module containing B doesn't have to import the one containing A:
# module b.py
class B(object):
def __init__(self, var_b):
self.var_b = var_b
def another_method(self, var):
return self.var_b + var
# module a.py
from b import B
class A(object):
def __init__(self, var_a, another_object):
self.var_a = var_a
self.another_object = another_object
def method(self):
return self.another_object.another_method(self.var_a)
if __name__ == "__main__":
b = b(1138)
a = A(b)
print a.method()
which avoids the circular import error you obviously have given your traceback.
At the beginning of popupWindow.py, put the line
from main import mainWindow
Then you can just call, e.g., mainWindow.clearListBox()
EDIT after OP posted code sample:
clearListBox is an instance method and as such can only be called on an instance, not on the class itself. You first have to instantiate an object of type mainWindow.
Based on your question and on your comment to #niceguy's answer, it's clear that the solution to your problem is to go read the python tutorial: Very soon you'll learn about modules (including import) and classes (including self, and calling class methods).
Edit: If you already understand about classes and instances, then here's your problem spelled out: Your class name is mainWindow, your instance is mainWin. You should be calling your functions on mainWin, e.g. mainWin.addScouts(1); not on mainWindow.
I have a class which i need to instantiate in order to call a method that it contains. When I access it from another class it works fine but when i run from terminal it says :
File "myClass.py", line 5, in <module>
class MyClass:
File "myClass.py", line 23, in ToDict
td=MyClass()
NameError: name 'MyClass' is not defined
Pasting the code:
class MyClass:
def convert(self, fl):
xpD = {}
# process some stuff
return xpD
if __name__ == "__main__":
source = sys.argv[1]
td = MyClass()
needed_stuff = td.convert(source)
print(needed_stuff)
The problem is that your if __name__ == "__main__" block is inside of your class definition. This will cause an error, as the code within the if will be run as part of the class being created, before the class been bound to a name.
Here's a simpler example of this error:
class Foo(object):
foo = Foo() # raises NameError because the name Foo isn't bound yet
If you format your code like this (that is, with the if unindented at the top level), it should work correctly:
class MyClass:
def convert(self, fl):
xpD = {}
# process some stuff
return xpD
if __name__ == "__main__":
source = sys.argv[1]
td = MyClass()
needed_stuff = td.convert(source)
print(needed_stuff)