import functools
from code.ghosts import Ghosts
class Pacman(QtGui.QGraphicsPixmapItem):
def __init__(self):
super(Pacman, self).__init__()
self.setPixmap(QtGui.QPixmap("pacman.png"))
def game_continue(self):
objects = list(self.scene().items())
for i in range(objects.__len__()):
if type(objects[i]) is Ghosts:
self.scene().removeItem(objects[i])
func = functools.partial(self.show_again, objects)
QtCore.QTimer.singleShot(100, func)
def show_again(self, objects):
for object_ in objects:
if type(object_) is Ghosts:
self.scene().addItem(object_)
It tells me that NoneType object has no attribute addItem (it's about self.scene() in the last row of the code). How come it recognizes the self.scene.removeItem() and executes it but there is no addItem?
QGraphicsScene QGraphicsItem.scene (self)
Returns the current scene for the item, or 0 if the item is not stored
in a scene.
http://pyqt.sourceforge.net/Docs/PyQt4/qgraphicsitem.html#scene
If you're calling removeItem() first then it will return None when calling addItem(). You can always store your QGraphicsScene instance in the item itself during its constructor method. That way it doesn't matter if the item belongs to the scene or not.
Related
it might be a silly question since I'm new to Python.
However, I hope someone can explain this because I try to find lots of resource but still hardly understand the mechanism behind.
So I create a Parent Class and a Child Class. Parent Class have set_name, get_name method
In Child Class, I defined a new method call Turn_Uppercase which calling get_name then uppercase the name. And when using Turn_Uppercase Method, I have to filled in Child Class Name, otherwise it would not work.
Can someone explain the mechanism here!
Let's me explain in code:
So first I create a Parent Class with get_name and set_name method.
class Parent:
def __init__(self, text_input):
self.__name = ""
self.name = text_input
#property #this is get_name
def name(self):
return self.__name
#name.setter #this is set_name
def name(self, text_input: str):
if isinstance(text_input, str): # check input has to be string
self.__name = text_input
else:
print('Wrong type of data')
Then I create a Child Class with new method called Turn_uppercase
class Child_to_parent(Parent):
def __init__(self):
pass
def turn_uppercase(self):
return self.name.upper()
Now I put in some object and use Turn_uppercase Method, I have to fill in Child Class Name
test1 = Child_to_parent
test1.name = "abcdef" # using parent method
print(f'{test1.turn_uppercase(Child_to_parent)}') # using child method
When using parent method through property name, I don't need to declare Child Class Name, but when it comes to use Turn_uppercase Method then I have to.
Why it works this way?
This line makes all the difference
test1 = Child_to_parent
You are not creating an object here, instead merely assigning a reference to the class itself. What you must be doing is
test1 = Child_to_parent() #>Create the object!
test1.name = "abcdef"
print(f'{test1.turn_uppercase()}')
Now why it works with the class? It's because you attached a attribute to the class called name. The method you called used the class as argument and evaluated the class attribute!
Read this answer for a better understanding!
I'm new in Python and I'm trying to get my head around how are managed attributes between methods of a class.
In the following example, I'm trying to modify a list in the method "regex" and use it afterwards in another method "printsc".
The "regex" part works without issues, but the attribute "self.mylist" is not updated so when I call "printsc" the result is "None".
class MyClass():
def __init__(self):
self.mylist = None
def regex(self, items):
self.mylist = []
for item in items:
if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", item):
self.mylist.append("IP:" + item)
else:
self.mylist.append("DNS:" + item)
return self.mylist
def printsc(self):
print(self.mylist)
items = ['192.168.0.1', 'hostname1', '10.0.1.15', 'server.local.fr']
MyClass().regex(items)
MyClass().printsc()
What am I missing ? What is the best way to achieve this goal ?
Thank you for your answers!
When you do MyClass(), it returns you an object.. And you are calling your methods on the object. Since you are doing it twice, each time a new object is created and regex and printsc are called on different objects.
what you should do is
myObj = MyClass()
myObj.regex(items)
myObj.printsc()
The problem is that when you do:
MyClass().regex(items)
MyClass().printsc()
You are creating 2 separate instances of MyClass, each of which will have a different .mylist attribute.
Either mylist is an instance attribute, and then this will work:
instance = MyClass()
instance.regex(items)
instance.printsc()
Or, if you want to share .mylist across instances, it should be
a class attribute:
class MyClass():
class_list = None
def __init__(self):
pass
def regex(self, items):
cls = self.__class__
if cls.class_list is None:
cls.class_list = []
for item in items:
if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", item):
cls.class_list.append("IP:" + item)
else:
cls.class_list.append("DNS:" + item)
return cls.class_list
def printsc(self):
# Going throuhgh `.__class__.` is actually optional for
# reading an attribute - if it is not in the instance
# Python will fetch it from the class instead.
# i.e. , the line bellow would work with `self.class_list`
print(self.__class__.class_list)
This way, the list persists across different instances of the class, as you try to do in your example.
You should create an object of the class:
a = MyClass()
a.regex(items)
a.printsc()
>>> ['IP:192.168.0.1', 'DNS:hostname1', 'IP:10.0.1.15', 'DNS:server.local.fr']
I need to minimize the response footprint of an API. One way we are doing that is eliminating attributes that are null. Which introduces the challenge to create a dataclass that I can build dynamically.
I have managed to get the dynamic class created and it contains the data I need (viewing in log). But, I have not been able to get it inserted into the Parent Class. ParentClass portion is Emtpy with this logic.
#dataclass
class VR: pass
#dataclass
class ResultParent:
validationResult: VR
matchCandidate: List[matchCandidates] = field(default_factory=list)
#create and pop dynamic class
vr = VR()
if valres.matchStatusCode is not None:
vr.matchStatusCode = valres.matchStatusCode
if valres.matchStatusReason is not None:
vr.matchStatusReason = valres.matchStatusReason
...
#This pprint works and the attr/values are what we want
pprint(vars(vr))
#Create ParentClass
obj = ResultParent([vr],[])
# The result of the above command is empty
#Code then continues on to populate matchCandidates and then the ParentClass - no issues there
I was able to accomplish this. I added a setattr that only added the attr if it was not NONE. Found it in this post. Which was the desired result.
#dataclass
class VR:
def __setattr__(self, name, value):
if value is not None:
self.__dict__[name] = value
#dataclass
class ResultParent:
validationResult: VR
matchCandidate: List[matchCandidates] = field(default_factory=list)
vr = VR()
vr.matchStatusCode = p.get('ValAddrStatus')
vr.matchStatusReason = p.get('ValAddrStatusCode')
...
obj = ResultParent([vars(vr)],[])
I would like to define a decorator that will register classes by a name given as an argument of my decorator. I could read from stackoverflow and other sources many examples that show how to derive such (tricky) code but when adapted to my needs my code fails to produce the expected result. Here is the code:
import functools
READERS = {}
def register(typ):
def decorator_register(kls):
#functools.wraps(kls)
def wrapper_register(*args, **kwargs):
READERS[typ] = kls
return wrapper_register
return decorator_register
#register(".pdb")
class PDBReader:
pass
#register(".gro")
class GromacsReader:
pass
print(READERS)
This code produces an empty dictionary while I would expect a dictionary with two entries. Would you have any idea about what is wrong with my code ?
Taking arguments (via (...)) and decoration (via #) both result in calls of functions. Each "stage" of taking arguments or decoration maps to one call and thus one nested functions in the decorator definition. register is a three-stage decorator and takes as many calls to trigger its innermost code. Of these,
the first is the argument ((".pdb")),
the second is the class definition (#... class), and
the third is the class call/instantiation (PDBReader(...))
This stage is broken as it does not instantiate the class.
In order to store the class itself in the dictionary, store it at the second stage. As the instances are not to be stored, remove the third stage.
def register(typ): # first stage: file extension
"""Create a decorator to register its target for the given `typ`"""
def decorator_register(kls): # second stage: Reader class
"""Decorator to register its target `kls` for the previously given `typ`"""
READERS[typ] = kls
return kls # <<< return class to preserve it
return decorator_register
Take note that the result of a decorator replaces its target. Thus, you should generally return the target itself or an equivalent object. Since in this case the class is returned immediately, there is no need to use functools.wraps.
READERS = {}
def register(typ): # first stage: file extension
"""Create a decorator to register its target for the given `typ`"""
def decorator_register(kls): # second stage: Reader class
"""Decorator to register its target `kls` for the previously given `typ`"""
READERS[typ] = kls
return kls # <<< return class to preserve it
return decorator_register
#register(".pdb")
class PDBReader:
pass
#register(".gro")
class GromacsReader:
pass
print(READERS) # {'.pdb': <class '__main__.PDBReader'>, '.gro': <class '__main__.GromacsReader'>}
If you don't actually call the code that the decorator is "wrapping" then the "inner" function will not fire, and you will not create an entry inside of READER. However, even if you create instances of PDBReader or GromacsReader, the value inside of READER will be of the classes themselves, not an instance of them.
If you want to do the latter, you have to change wrapper_register to something like this:
def register(typ):
def decorator_register(kls):
#functools.wraps(kls)
def wrapper_register(*args, **kwargs):
READERS[typ] = kls(*args, **kwargs)
return READERS[typ]
return wrapper_register
return decorator_register
I added simple init/repr inside of the classes to visualize it better:
#register(".pdb")
class PDBReader:
def __init__(self, var):
self.var = var
def __repr__(self):
return f"PDBReader({self.var})"
#register(".gro")
class GromacsReader:
def __init__(self, var):
self.var = var
def __repr__(self):
return f"GromacsReader({self.var})"
And then we initialize some objects:
x = PDBReader("Inside of PDB")
z = GromacsReader("Inside of Gromacs")
print(x) # Output: PDBReader(Inside of PDB)
print(z) # Output: GromacsReader(Inside of Gromacs)
print(READERS) # Output: {'.pdb': PDBReader(Inside of PDB), '.gro': GromacsReader(Inside of Gromacs)}
If you don't want to store the initialized object in READER however, you will still need to return an initialized object, otherwise when you try to initialize the object, it will return None.
You can then simply change wrapper_register to:
def wrapper_register(*args, **kwargs):
READERS[typ] = kls
return kls(*args, **kwargs)
I'm trying to create a version of QListWidget (in PySide) in which the itemClicked signal will carry not one item, but a list of all items in the QListWidget.
I tried different things, but no luck so far. This is what I have ATM:
class RelationsListWidget(QListWidget):
all_items = Signal(list)
item_list = []
def __init__(self):
QListWidget.__init__(self)
self.itemClicked.connect(self.gather_items)
def gather_items(self):
self.item_list = [self.item(i) for i in range(self.count())]
self.all_items.emit(self.item_list)
but when I connect it:
class NodeEditWindow(QDialog):
...
self.list_consumes = RelationsListWidget()
self.list_consumes.itemClicked.connect(self.create_SelectRelationsWindow)
...
#Slot(object)
def create_SelectRelationsWindow(self, list_widget):
print("create_SelectRelationsWindow: %s" % type(list_widget))
I'm getting:
create_SelectRelationsWindow: <class '__main__.NodeItem'>
so it carries only one item, not a list.
related questions:
How to connect custom signal to slot in pyside with the new syntax?
PyQt4.QtCore.pyqtSignal object has no attribute 'connect'