Some trouble with python scope and objects - python

class Thing:
def __init__ (self, a, b, c,):
self.a = a
self.b = b
self.c = c
stuff = Thing("apples","butter","charlie")
otherThing = stuff
def doTheThings():
if(otherThing.a == "apples"):
print("done")
doTheThings()
I'm having a problem with the second line of the "doTheThings" function, and I have no idea what's wrong. Any help would be very appreciated.

I think add somthing maybe solve your problem.
if __name__ =="__main__":
doTheThings()
beacuse this is access of python code.

Related

Python OOP output return is wrong, someone has an idea?

I'm currently learning how to write object oriented programming in python and I have this code I wrote (well part of it, some of it is part of the class I'm following)
class Toolbox:
def __init__(self, tool):
pass
class Hammer:
def __init__(self, color):
pass
class Screwdriver:
def __init__(self, size):
pass
class Screw:
MAX_TIGHTNESS = 5
def __init__(self):
self.tightness = 0
def loosen(self):
if (self.tightness > 0):
self.tightness -= 1
def tighten(self):
if (self.tightness < self.MAX_TIGHTNESS):
self.tightness += 1
def __str__(self):
return "Screw with tightness {}".format(self.tightness)
class Nail:
def __init__(self):
self.in_wall = False
def nail_in(self):
if (not self.in_wall):
self.in_wall = True
def remove(self):
if (self.in_wall):
self.in_wall = False
def __str__(self):
return "Nail {}in wall.".format("" if self.in_wall else "not ")
hammer = Hammer("blue")
sdriver = Screwdriver("300")
#tbox = Toolbox()
tool1 = Toolbox(hammer)
tool2 = Toolbox(sdriver)
screw1 = Screw()
print(screw1)
screw1.tighten()
print(screw1)
nail1 = Nail()
print(nail1)
nail1.nail_in
print(nail1)
The output of print(screw1) works but print(nail1) gives me the same output (Nail in wall.) twice instead Nail in wall. I guess there's a problem in my logic and I can't seem to figure it out. Can someone help me?
Thanks!
Marc
You need to call nail_in - just as you are already doing with screw1.tighten. So do this (note the brackets here):
nail1.nail_in()
With this fix, your code works:
Screw with tightness 0
Screw with tightness 1
Nail not in wall.
Nail in wall.
By referring to the function but without the brackets, it is a syntactically valid line of code, but it is just an expression for the function object itself, and as you are not doing anything with it (such as assigning it to a variable), it is then simply discarded.

python super :TypeError: __init__() takes 2 positional arguments but 3 were given

every one I am practicing Python, and I found something strange, here is my code
LogicG.py
class LogicGate:
def __init__(self,n):
self.label = n
self.output = None
def getLabel(self):
return self.label
def getOutput(self):
self.output = self.performGateLogic()
return self.output
class BinaryGate(LogicGate):
def __init__(self,n):
LogicGate.__init__(self,n)
self.pinA = None
self.pinB = None
def getPinA(self):
return int(input("Enter Pin A input for gate "+ self.getLabel()+"-->"))
def getPinB(self):
return int(input("Enter Pin B input for gate "+ self.getLabel()+"-->"))
class UnaryGate(LogicGate):
def __init__(self,n):
LogicGate.__init__(self,n)
self.pin = None
def getPin(self):
return int(input("Enter Pin input for gate "+ self.getLabel()+"-->"))
class AndGate(BinaryGate):
def __init__(self,n):
super(AndGate,self).__init__(self,n)
def performGateLogic(self):
a = self.getPinA()
b = self.getPinB()
if a==1 and b==1:
return 1
else:
return 0
however, it shows the error below, I use python 3.6.4
after I mark out the code "the super" it can work ok
super(AndGate,self).init(self,n)
class AndGate(BinaryGate):
# def __init__(self,n):
# super(AndGate,self).__init__(self,n)
def performGateLogic(self):
a = self.getPinA()
b = self.getPinB()
if a==1 and b==1:
return 1
else:
return 0
above those code just I copy from this site for python study, see that site in Listing 11, it shows these code work, but when I copy to my computer the code did not work?? I have to mark out "super" part?? why? thank you
When using super, self is passed automatically.
Also, in Python3.3 and above, super does not even need to receive arguments to know from which class it is being called. You can simply do this.
super().__init__(n)
This greatly improves maintainability, so it would be the prefered approach.
If you are using Python 3.3 and above, you should replace
LogicGate.__init__(self,n)
with
super().__init__(n)
It is better to use this format when ever you want to call super class constructor.
You don't need to pass self here:
super(AndGate,self).__init__(self,n)
It should be
super(AndGate,self).__init__(n)

Python - Creating a bunch of variables dynamically

I'm new to Python and I have made a piece of code that looks like this:
class Ui(QWidget):
def __init__(self):
super(Ui, self).__init__()
uic.loadUi('logotest.ui', self)
iposter1 = QPixmap('images/1.jpg')
iposter2 = QPixmap('images/2.jpg')
iposter3 = QPixmap('images/3.jpg')
iposter4 = QPixmap('images/4.jpg')
self.poster1.setPixmap(iposter1)
self.poster2.setPixmap(iposter2)
self.poster3.setPixmap(iposter3)
self.poster4.setPixmap(iposter4)
The code does this: Set 4 images (1-4.jpg) as QPixmaps(iposter*) and use them for 4 QLabel objects(self.poster*).
However as I have a lot of images to process I wanted to use a function to do those jobs for me, so I wrote:
def setPoster(a):
imagelink = "images/" + str(a) + ".jpg"
iposter, a = QPixmap(imagelink)
self.poster, a.setPixmap(iposter, a)
...
setPoster(1)
But this does not work as Python gives me an error of TypeError: 'QPixmap' object is not iterable. What should I do to fix it?
Thanks!
You can use getattr and setattr like this. I haven't fully under stand your requests. Why can you use self.poster4 directly? I think the code below may help you.
for i in range(100):
iposter = QPixmap('images/3.jpg')
poster = getattr(self, 'iposter%d' % i)
poster.setPixmap(iposter)
update
class Ui(QWidget):
def __init__(self):
super(Ui, self).__init__()
uic.loadUi('logotest.ui', self)
def setPoster(self, a):
iposter = QPixmap('images/%d.jpg' % a)
poster = getattr(self, 'iposter%d' % a)
poster.setPixmap(iposter)
all python variables are just dictionary keys. if you want you can add variables to an object like this
object.dict()["variable"] = 1
or if you want to do it globally
global()["variable"] = 1

Access "a method of a class" in "a function of another python file" by passing the class as that function's parameter

I have a class file. Let's call it "C1.py". The sample code looks like below.
class C1(object):
def __init__(self):
self.greeting = "Hello, world!"
def M1(ans):
if ans == 1 or ans == 2:
return True
else:
return False
Now, I have another python file in the same folder, which will access the class file shown above.
from trial import C1
def getAns(class1):
while True:
ans = input("Answer: ")
if class1.M1(ans):
return ans
break
sample = C1()
print sample.greeting
ans = getAns(sample)
print ans
When I run those files, sample.greeting prints fine. Everything is fine until when the execution reaches the line "ans = getAns(C1)", which gives the error "M1() takes exactly 1 argument (2 given)".
So, where in the code should I change so that I can call that method successfully?
Note here that the above code is only the abstraction of my whole program to highlight my problem. It sounds stupid with just the code above alone. So, please, please bear with that for me.
M1 is currently defined as a method of C1, as such it needs to have an additional self argument which would be the instance of the class. I.e
class C1(object):
def __init__(self):
self.greeting = "Hello, world!"
def M1(self, ans):
if ans == 1 or ans == 2:
return True
else:
return False
In other languages such as C++ or Java the presence of self (or this) is implicit, but in python it's explicit.
alternatively if you don't want or need M1 to access C1's state you could make M1 static via #staticmethod i.e.
class C1(object):
def __init__(self):
self.greeting = "Hello, world!"
#staticmethod
def M1(ans):
if ans == 1 or ans == 2:
return True
else:
return False

Python pickle instance variables

I am doing some calculations on an instance variable, and after that is done I want to pickle the class instance, such that I don't have to do the calculations again. Here an example:
import cPickle as pickle
class Test(object):
def __init__(self, a, b):
self.a = a
self.b = b
self.c = None
def compute(self, x):
print 'calculating c...'
self.c = x * 2
test = Test(10, 'hello')
test.compute(6)
# I have computed c and I want to store it, so I don't have to recompute it again:
pickle.dump(test, open('test_file.pkl', 'wb'))
After test.compute(6) I can check to see what test.__dict__ is:
>>> test.__dict__
{'a': 10, 'c': 12, 'b': 'hello'}
I thought that is what going to get pickled; however,
When I go to load the class instance:
import cPickle as pickle
from pickle_class_object import Test
t2 = pickle.load(open('test_file.pkl', 'rb'))
I see this in the shell:
calculating c...
Which means that I did not pickle c and I am computing it over again.
Is there a way to pickle test how I want to? So I don't have to compute c over again. I see that I could just pickle test.__dict__, but I am wondering if there is a better solutions. Also, my understanding about what is going on here is weak, so any comment about what is going would be great. I've read about __getstate__ and __setstate__, but I don't see how to apply them here.
You are importing the pickle_class_object module again, and Python runs all code in that module.
Your top-level module code includes a call to .compute(), that is what is being called.
You may want to move the code that creates the pickle out of the module, or move it to a if __name__ == '__main__': guarded section:
if __name__ == '__main__':
test = Test(10, 'hello')
test.compute(6)
pickle.dump(test, open('test_file.pkl', 'wb'))
Only when running a python file as the main script is __name__ set to __main__; when imported as a module __name__ is set to the module name instead and the if branch will not run.
Pickling works as you expect it to work. The problem here is when you run the new script, you import the module that contains the class Test. That entire module is run including the bit where you create test.
The typical way to handle this sort of thing would be to protect the stuff in a if __name__ == "__main__: block.
class Test(object):
def __init__(self, a, b):
self.a = a
self.b = b
self.c = None
def compute(self, x):
print 'calculating c...'
self.c = x * 2
if __name__ == "__main__":
import cPickle as pickle
test = Test(10, 'hello')
test.compute(6)
# I have computed c and I want to store it, so I don't have to recompute it again:
pickle.dump(test, open('test_file.pkl', 'wb'))
That isn't what's happening. You import a python module that has code in it at the top level, which executes when you import the module. You can see that your code works as you intended:
import cPickle as pickle
class Test(object):
def __init__(self, a, b):
self.a = a
self.b = b
self.c = None
def compute(self, x):
print 'calculating c...'
self.c = x * 2
test = Test(10, 'hello')
test.compute(6)
pickle.dump(test, open('test_file.pkl', 'wb'))
t2 = pickle.load(open('test_file.pkl', 'rb'))
print t2.c
--output:--
calculating c...
12
If your code worked as you describe, then you would see "calculating c..." twice.

Categories

Resources