Questions about python module - python

It is my first time learning PyQt5.
While I read code related to PyQt5, I have a question some modules.
Is 'isStarted' a variable or in a module?
def __init__(self):
super().__init__()
self.isStarted = False
self.isPaused = False
self.nextMove = None
self.lastShape = Shape.shapeNone

def __init__(self):
super().__init__()
self.isStarted = False
self.isPaused = False
self.nextMove = None
self.lastShape = Shape.shapeNone
Whenever there is an =, rest assured that anything on the left side is a variable. In this case, you are making isStarted variable an attribute of self which is the class in which your code is in. So you can call it from other classes like: print(App.isStarted) (of course, replace App with whatever your class is named.

Related

Python set class variable after calling

I'm making a game using the pygame module and I have a player class:
class Player(pygame.sprite.Sprite):
def __init__(self, name, position, axsis, movment, idle, walk = None, jump = None):
pygame.sprite.Sprite.__init__(self)
self.name = name
self.idle = idle
self.walk = walk
self.jump = jump
self.image = self.idle[0]
self.movment = movment
self.left, self.right = axsis
self.pos = vec(position[0],position[1])
I am adding my characters using json data type and trying to add animations after calling the class but i can't do it
Sample code
class Game():
def __init__(self,json_file):
self.player_attribute = json_file
def character(self):
self.npc = []
for i in self.player_attribute:
self.npc.append(Player(i['name'],
i['position'],
i['axsis'],
i['movment']))
self.animation()
return self.npc
def add_animation(self):
for i in self.npc:
i.idle = "images\ghost.png"
def main_loop()
self.character
when i try this i get an error
self.image = self.idle[0]
TypeError: init() missing 1 required positional argument: 'idle'
how can i add the variables of the class after calling the class
It is not clear what the 'idle' parameter is supposed to represent in your code. However, the reason for the exception is that you are not passing any argument for 'idle' when constructing the Player object. You need something like:
self.npc.append(Player(i['name'],
i['position'],
i['axsis'],
i['movment'],
i['idle']))
You can either do that or alternatively you can pass a default argument to the Player constructor so that, when initializing you do not need to explicitly pass idle:
class Player(pygame.sprite.Sprite):
def __init__(self, name, position, axsis, movment, idle=[1], walk = None, jump = None):
You can modify its content at a later time, however I suggest you are careful what you instantiate that object attribute as, because it might come bite you back later (type error or value error).
If it were me, I would move this out of init, or not build the object until all values and their types are known (see Builder Design Pattern).
Hope this helped :) Cheers!

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.

How to tell if two QPushButtons have been pressed (Python)

I need to call a member function when both of my QPushButtons have been pressed. I cannot find a way to keep track of if they have been pressed.
I call a function when either of the buttons are clicked using ...clicked.connect(func) and within that function I have tried to: 1) return a value, 2) update a member variable. Below I have shown how I tried to create and update member variable and use a conditional to see if both variables were true so that I could call my next function.
def __init__(self, parent=None):
super(MorphingApp, self).__init__(parent)
self.setupUi(self)
self.startIm = None
self.endIm = None
self.initialState()
def initialState(self):
self.btn_loadStart.clicked.connect(self.loadImageS)
self.btn_loadEnd.clicked.connect(self.loadImageE)
if(self.startIm is True and self.endIm is True):
self.loadedState()
def initialState(self):
self.startIm = True
def loadImageE(self):
self.endIm = True
My functions of course do things, but I removed parts that were irrelevant. When I run the GUI I am able to load the images but the function that is supposed to be called after both buttons have been pushed is not called. I know this because the state of the GUI is not changing as I intend.
This is my first time posting a question so let me know how to improve :)
Use a simple True/False flag to check if the button has been pressed at least once. Both buttons start with the flag set to False, so we can set that up in the init method.
Then place the code that checks to see if both buttons have been pressed inside the functions connected to them. Finally, simply call the respective "final" function if the check passes.
This is an example using two generic buttons:
def __init__(self, parent=None):
super(MorphingApp, self).__init__(parent)
self.btn_01_pressed = False
self.btn_02_pressed = False
self.set_buttons()
def set_buttons(self):
self.btn_01.clicked.connect(self.check01)
self.btn_02.clicked.connect(self.check02)
def check01(self):
self.btn_01_pressed = True
if self.btn_01_pressed is True and self.btn_02_pressed is True:
self.call_final_function()
def check02(self):
self.btn_02_pressed = True
if self.btn_01_pressed is True and self.btn_02_pressed is True:
self.call_final_function()
def call_final_function(self):
# do something great here
Like in your post I've ommited some parts necessary for the actual code (like creating the QPushButton widgets), but hopefully you get the idea.
def __init__(self, parent=None):
super(MorphingApp, self).__init__(parent)
self.setupUi(self)
self.startIm = False
self.endIm = False
self.btn_loadStart.clicked.connect(self.loadImageS)
self.btn_loadEnd.clicked.connect(self.loadImageE)
def loadImageS(self):
self.startIm = True
if self.startIm and self.endIm:
self.loadedState()
def loadImageE(self):
self.endIm = True
if self.startIm and self.endIm:
self.loadedState()

Instantiating a unique object every time when using object composition?

As an example, just a couple of dummy objects that will be used together. FWIW this is using Python 2.7.2.
class Student(object):
def __init__(self, tool):
self.tool = tool
def draw(self):
if self.tool.broken != True:
print "I used my tool. Sweet."
else:
print "My tool is broken. Wah."
class Tool(object):
def __init__(self, name):
self.name = name
self.broken = False
def break(self):
print "The %s busted." % self.name
self.broken = True
Hammer = Tool(hammer)
Billy = Student(Hammer)
Tommy = Student(Hammer)
That's probably enough code, you see where I'm going with this. If I call Hammer.break(), I'm calling it on the same instance of the object; if Billy's hammer is broken, so is Tommy's (it's really the same Hammer after all).
Now obviously if the program were limited to just Billy and Tommy as instances of Students, the fix would be obvious - instantiate more Hammers. But clearly I'm asking because it isn't that simple, heh. I would like to know if it's possible to create objects which show up as unique instances of themselves for every time they're called into being.
EDIT: The kind of answers I'm getting lead me to believe that I have a gaping hole in my understanding of instantiation. If I have something like this:
class Foo(object):
pass
class Moo(Foo):
pass
class Guy(object):
def __init__(self, thing):
self.thing = thing
Bill = Guy(Moo())
Steve = Guy(Moo())
Each time I use Moo(), is that a separate instance, or do they both reference the same object? If they're separate, then my whole question can be withdrawn, because it'll ahve to make way for my mind getting blown.
You have to create new instances of the Tool for each Student.
class Student(object):
def __init__(self, tool):
self.tool = tool
def draw(self):
if self.tool.broken != True:
print "I used my tool. Sweet."
else:
print "My tool is broken. Wah."
class Tool(object):
def __init__(self, name):
self.name = name
self.broken = False
def break(self):
print "The %s busted." % self.name
self.broken = True
# Instead of instance, make it a callable that returns a new one
def Hammer():
return Tool('hammer')
# Pass a new object, instead of the type
Billy = Student(Hammer())
Tommy = Student(Hammer())
I'll try to be brief. Well.. I always try to be brief, but my level of success is pretty much random.randint(0, never). So yeah.
Lol. You even failed to be brief about announcing that you will try to be brief.
First, we need to be clear about what "called into being" means. Presumably you want a new hammer every time self.tool = object happens. You don't want a new instance every time, for example, you access the tool attribute, or you'd always a get a new, presumably unbroken, hammer every time you check self.tool.broken.
A couple approaches.
One, give Tool a copy method that produces a new object that should equal the original object, but be a different instance. For example:
class Tool:
def __init__(self, kind):
self.kind = kind
self.broken = False
def copy(self):
result = Tool(self.kind)
result.broken = self.broken
return result
Then in Student's init you say
self.tool = tool.copy()
Option two, use a factory function.
def makehammer():
return Tool(hammer)
class Student:
def __init__(self, factory):
self.tool = factory()
Billy = Student(makehammer)
I can't think any way in Python that you can write the line self.tool = object and have object automagically make a copy, and I don't think you want to. One thing I like about Python is WYSIWYG. If you want magic use C++. I think it makes code hard to understand when you not only can't tell what a line of code is doing, you can't even tell it's doing anything special.
Note you can get even fancier with a factory object. For example:
class RealisticFactory:
def __init__(self, kind, failurerate):
self.kind = kind
self.failurerate = failurerate
def make(self):
result = Tool(self.kind)
if random.random() < self.failurerate:
result.broken = True
if (self.failurerate < 0.01):
self.failurerate += 0.0001
return result
factory = RealisticFactory(hammer, 0.0007)
Billy = Student(factory.make)
Tommy = Student(factory.make) # Tommy's tool is slightly more likely to be broken
You could change your lines like this:
Billy = Student(Tool('hammer'))
Tommy = Student(Tool('hammer'))
That'll produce a distinct instance of your Tool class for each instance of the Student class. the trouble with your posted example code is that you haven't "called the Tool into being" (to use your words) more than once.
Just call Tool('hammer') every time you want to create a new tool.
h1 = Tool('hammer')
h2 = Tool('hammer')
Billy = Student(h1)
Tommy = Student(h2)
Oh wait, I forgot, Python does have magic.
class Student:
def __setattr__(self, attr, value):
if attr == 'tool':
self.__dict__[attr] = value.copy()
else:
self.__dict__[attr] = value
But I still say you should use magic sparingly.
After seeing the tenor of the answers here and remembering the Zen of Python, I'm going to answer my own dang question by saying, "I probably should have just thought harder about it."
I will restate my own question as the answer. Suppose I have this tiny program:
class Item(object):
def __init__(self):
self.broken = False
def smash(self):
print "This object broke."
self.broken = True
class Person(object):
def __init__(self, holding):
self.holding = holding
def using(self):
if self.holding.broken != True:
print "Pass."
else:
print "Fail."
Foo = Person(Item())
Bar = Person(Item())
Foo.holding.smash()
Foo.using()
Bar.using()
The program will return "Fail" for Foo.using() and "Pass" for Bar.using(). Upon actually thinking about what I'm doing, "Foo.holding = Item()" and "Bar.holding = Item()" are clearly different instances. I even ran this dumpy program to prove it worked as I surmised it did, and no surprises to you pros, it does. So I withdraw my question on the basis that I wasn't actually using my brain when I asked it. The funny thing is, with the program I've been working on, I was already doing it this way but assuming it was the wrong way to do it. So thanks for humoring me.

Binding checkbox to string in IronPython

How can I bind a checkbox to a string such that when the checkbox is checked/unchecked, the value of the string changes? I have this (with CheckAll as my checkbox):
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'BioApp1.xaml')
openDialog = SequenceFileOperations()
self.Sequences = openDialog.Open()
object = MyObjects(self.Sequences)
self.CheckAll.DataContext = object
self.IDLabel.DataContext = object
class MyObjects(object):
def __init__(self, Sequences):
self.CurrentSeq = Sequences[0]
self.ID = self.CurrentSeq.ID
and
<Label Height="28" HorizontalAlignment="Left" Margin="152,221,0,0" VerticalAlignment="Top" Width="98" Name="IDLabel" Content="{Binding Path=ID}"/>
I want that when the checkbox is unchecked, the label should display the sequence ID, but when it is checked, it should simply display “All”. For this I need to change the ID property of CurrentSeq to “All”. How do I do that by data binding? Is there any other way I can do this?
EDIT: I feel really stupid but I just can’t get this to work. I have been trying to follow the suggestion about using getter/setter but I guess I don’t know enough. Before doing anything more complicated, I simply want to make a button disabled when I tick the checkbox and enable it when I uncheck it. This is what I wrote:
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'App1.xaml')
object = BindingClass(self.Check, self.PreviousBtn)
self.PreviousBtn.DataContext = object
class BindingClass(object):
def __init__(self, Check, PreviousBtn):
self.Check = Check
self.PreviousBtn = PreviousBtn
def GetEnabledConverter(self):
if self.CheckAll.IsChecked:
return self.PreviousBtn.IsEnabled
def SetEnabledConverter(self):
if self.CheckAll.IsChecked:
self.PreviousBtn.IsEnabled = False
else:
self.PreviousBtn.IsEnabled = True
EnabledConverter = property(GetEnabledConverter, SetEnabledConverter)
And:
<Button Content="Previous" IsEnabled="{Binding Path=EnabledConverter}" />
Unfortunately there is no error but no effect either. The code does not do anything. Would really appreciate if you could help me out with this.
EDIT2: Using the notify_property, I tried this:
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'Test.xaml')
c = Converters(self.check1, self.Button)
self.Button.DataContext = c
class Converters(NotifyPropertyChangedBase):
def __init__(self, check, button):
super(Converters, self).__init__()
self.Check = check
self.Button = button
#notify_property
def ButtonEnabled(self):
return self.Button.IsEnabled
#ButtonEnabled.setter
def ButtonEnabled(self):
if self.Check.IsChecked:
self.Button.IsEnabled = False
else:
self.Button.IsEnabled = True
Still the same result: no effect. I just cannot understand where the problem is.
I would use Converter.
Edit:
You can implement converter in Python:
class BoolToVisibilityConverter(IValueConverter):
def Convert(self, value, targetType, parameter, culture):
return Visibility.Visible if value != val else Visibility.Collapsed
Last time I worked with WPF in IronPython, you could not use it directly in .xaml. I am not sure whether it has improved in 2.7.
Another possibility is to add another property which does the conversion (converted_ID) in its setter/getter. Thinking more about it, I would do rather this, because the code is in one place.
Edit 2:
Make sure, you are using notify_property instead of classic Python property.

Categories

Resources