I'm working on a simple game in python (which I'm fairly new to as a language) using pygame and it seems as though python really hates circular dependencies (although I'm aware there are ways around this).
Generally for collision detection, I would have a callback function that is called, once a collision is detected, for each object involved in the collision. The problem is that in doing so, each object involved in the collision would need to know about the other in order to resolve the collision in the correct way, thus resulting in a circular dependency which I would prefer to avoid (see below).
Here is the Enemy.py module:
from Player include * #dependency on player
class Enemy():
def handle_collision(other_object):
if isinstance(other_object,Player) #this check requires the Enemy class to know about Player
Here is the Player.py module:
from enemy include * #dependency on enemy
class Player():
def handle_collision(other_object):
if isinstance(other_object,Wall):
#do what we need to do to resolve a wall collision
elif isinstance(other_object,Enemy): #this check requires that we include the Enemy class
#do what we need to do to resolve an enemy collision
Any suggestions or insight into how this is generally handled would be great.
Cyclic dependencies like these, where the module player.py imports the module enemy.py and vice versa are indeed rather tricky in Python. But there are (at least) two ways to work around those:
First, you do not need to import a module to use classes from that module. Even without importing the enemy.py module, you can use an instance of the Enemy class, e.g. after it has been passed to the handle_collision method as a parameter by some other module. Then, you could work around your problem by checking e.g. for other_object.__class__.__name__ == 'Enemy'.
This works, but it is not very nice, and will cause problems with, e.g., subclasses of Enemy.
Second, you do not have to put each class in it's own module/file, as it is common in, e.g., Java. In Python, it is perfectly normal and good practice to put many related classes in one and the same module. (One of the reasons why cyclic dependencies between modules are discouraged in Python is because needing them is considered a sign of bad system design.)
So my advice would be to put all of your "entity" classes into the same module, e.g. entities.py
class Entity:
def handle_collision(self, other_object):
pass
class Player(Entity):
def handle_collision(self, other_object):
if isinstance(other_object, Enemy):
# do stuff
class Enemy(Entity):
def handle_collision(self, other_object):
if isinstance(other_object, Player):
# do other stuff
Note that circular imports are in fact possible in Python, but should be used with care. For more about this, you can take a look at these two related posts.
You can generally eliminate circular dependency errors by moving the import from the module-level into a function or method where you actually need it.
In Player.py, try moving from enemy include * (which should be IMPORT, not INCLUDE) to be within your handle_collision method:
def handle_collision(other_object):
from enemy import Enemy
if isinstance(other_object,Wall):
#do what we need to do to resolve a wall collision
pass
elif isinstance(other_object,Enemy):
#this check requires that we include the Enemy class
pass
#do what we need to do to resolve an enemy collision
Also you should try to avoid importing * as it makes it difficult to see where your various imported names come from.
Related
I'm currently developing a small game with pygame and I'm having a hard time figuring out a way to check for collisions. I've found this question, but I can't use the pygame.sprite.spritecollide(player, wall_group, True) because my called player isn't a 'sprite', it's a class that I've created (that uses the functionality of normal shapes (https://www.pygame.org/docs/ref/draw.html)).
If anyone could figure a way that I can detect collisions and explain to me shortly about the difference between 'sprite' and just a normal shape like circle/rectangle I would appreciate it.
To use pygame's collition detection funcions (like pygame.sprite.spritecollide), your class does not need to be a subclass of pygame's Sprite.
Thanks to python's duck typing, the actual class does not matter, as long as your class behaves like a Sprite. In this context, it just means that your class should have a rect attribute, and it should be a Rect (again, technically, it does not need to be a Rect, only "look like" one).
Given a simple class like this:
>>> class Foo():
... def __init__(self):
... self.rect=pygame.rect.Rect(100, 100, 100, 100)
we can use pygame.sprite.spritecollide like this:
>>> f=Foo()
>>> g=Foo()
>>> pygame.sprite.spritecollide(f, [g], False)
[<__main__.Foo instance at 0x0000000003C6DF48>]
Also see how the second argument isn't a Group, but a simple List, but python does not care, since the only thing that matters in this case is that you can iterate over the object. If you would pass True as the third argument, this would fail, since spritecollide would try to call sprites() and the second argument and kill() on the elements inside.
Likewise, if you want to e.g. use pixel perfect collision detection, you need a mask attribute etc. So you should use the Sprite class anyway since it offers some more stuff like managing groups. Also, everytime you want to store a position or a size, consider using pygame's Rect class, since it's quite powerfull and it's used/expected in a lot of pygame functions.
tl;dr: Use pygame's Sprite class. There's probably no good reason for you to not do it, and a bunch of good reason to actually use it.
The django-file-resubmit module (file widgets.py) makes this import:
from django.forms import ClearableFileInput
and then it defines class based on ClearableFileInput:
class ResubmitBaseWidget(ClearableFileInput):
# ...some code
I try to use the module with different base class and it works well. But I have to patch the import command in module code. (DBAdminClearableFileInput is inherited from django.forms.ClearableFileInput in an other 3rd party module):
from db_file_storage.form_widgets import DBAdminClearableFileInput as ClearableFileInput
My question is: Could the code of django-file-resubmit module be rewritten more clever, so it could be used with DBAdminClearableFileInput as parameter?
Note: I'm not sure if this is not duplicate question. However I think here are special problems of modules design and a question if some Pull Request could be made or what is the best approach how to use both modules without changing them.
It sounds like what you might really want is co-operative multiple inheritance. E.g. You want to have
class MyFileInput(DBAdminClearableFileInput, ResubmitBaseWidget):
pass
For that to work, both DBAdminClearableFileInput and ResubmitBaseWidget would need to be written with co-operative multiple inheritance in mind. It may not even be (theoretically) possible depending on how the end-state behaviour has to look. E.g. if DBAdminClearableFileInput wants to render the widget as <foo> and ResubmitBaseWidget wants to render the widget as <bar>, one of them has to 'win' (in the absence of additional code you might write yourself in MyFileInput.
It's possible (though probably unlikely) that multiple inheritance will 'just work', depending on what methods etc both those classes override and whether they make they already make the correct calls to super().
It's probably worth a try at least, in the worst case scenario you can add some 'glue' to your MyFileInput class to make it work.
Here's a trite example
class Elephant: # Represents ClearableFileInput
def colour(self):
return "Grey"
class BrownElephant(Elephant): # Represents ResubmitBaseWidget
def colour(self):
return "Brown"
class PinkElephant(Elephant): # Represents DBAdminClearableFileInput
def colour(self):
return "Pink"
Now, at the moment, these classes do not cooperate, and so if you do multiple inheritance, you get:
class BrownAndPinkElephant(BrownElephant, PinkElephant):
pass
nelly = BrownAndPinkElephant()
print(nelly.colour())
Will print "Brown", since the Method Resolution Order starts with BrownElephant, which returns "Brown" without ever calling super().colour(), and so Pink and 'default' Elephant's methods are never even called.
You could 'fix' this in a very limited (but might be enough for your purposes) with a hacky 'glue' method like this:
class BrownAndPinkElephant(BrownElephant, PinkElephant):
def colour(self):
colours = [
BrownElephant.colour(self),
PinkElephant.colour(self),
]
return " and ".join(colours)
nelly = BrownAndPinkElephant()
print(nelly.colour())
Now the printed output is "Brown and Pink", which is more sensible (at least within the context of this example!). Hopefully you can see that you attempt to implement similar things for a subclass of DBAdminClearableFileInput, ResubmitBaseWidget to give you control over what aspects of each class end up being used in the final class.
It's worth saying, there are an awful lot of pitfalls with this approach and I wouldn't recommend it for anything 'serious'. However, when you have 2 classes with a common base class, that you want to combine, and you don't control the source code of either, then this may be a possible solution.
I have a sprite and when it collides with another object I want it to increase the score that the user gets. However I am unsure how to export the fact that the sprite has collided to another part of my program. This is what I tried:
def checkCollision(self, sprite):
if self.rect.colliderect(sprite.rect):
self.x=3000
self.score=score+100
However it ignore the fact the score has increased despite me having made score global.
Any help would be appreciated.
I'm assuming that the collision function you provided is part of your player class. Making that assumption, you could simply assign the global score to = x.score (x = whatever you named that particular player object) Obviously this is less than ideal but it's a simple way to stick in the functionality you're looking for.
I'm coding a poker hand evaluator as my first programming project. I've made it through three classes, each of which accomplishes its narrowly-defined task very well:
HandRange = a string-like object (e.g. "AA"). getHands() returns a list of tuples for each specific hand within the string:
[(Ad,Ac),(Ad,Ah),(Ad,As),(Ac,Ah),(Ac,As),(Ah,As)]
Translation = a dictionary that maps the return list from getHands to values that are useful for a given evaluator (yes, this can probably be refactored into another class).
{'As':52, 'Ad':51, ...}
Evaluator = takes a list from HandRange (as translated by Translator), enumerates all possible hand matchups and provides win % for each.
My question: what should my "domain" class for using all these classes look like, given that I may want to connect to it via either a shell UI or a GUI? Right now, it looks like an assembly line process:
user_input = HandRange()
x = Translation.translateList(user_input)
y = Evaluator.getEquities(x)
This smells funny in that it feels like it's procedural when I ought to be using OO.
In a more general way: if I've spent so much time ensuring that my classes are well defined, narrowly focused, orthogonal, whatever ... how do I actually manage work flow in my program when I need to use all of them in a row?
Thanks,
Mike
Don't make a fetish of object orientation -- Python supports multiple paradigms, after all! Think of your user-defined types, AKA classes, as building blocks that gradually give you a "language" that's closer to your domain rather than to general purpose language / library primitives.
At some point you'll want to code "verbs" (actions) that use your building blocks to perform something (under command from whatever interface you'll supply -- command line, RPC, web, GUI, ...) -- and those may be module-level functions as well as methods within some encompassing class. You'll surely want a class if you need multiple instances, and most likely also if the actions involve updating "state" (instance variables of a class being much nicer than globals) or if inheritance and/or polomorphism come into play; but, there is no a priori reason to prefer classes to functions otherwise.
If you find yourself writing static methods, yearning for a singleton (or Borg) design pattern, writing a class with no state (just methods) -- these are all "code smells" that should prompt you to check whether you really need a class for that subset of your code, or rather whether you may be overcomplicating things and should use a module with functions for that part of your code. (Sometimes after due consideration you'll unearth some different reason for preferring a class, and that's allright too, but the point is, don't just pick a class over a module w/functions "by reflex", without critically thinking about it!).
You could create a Poker class that ties these all together and intialize all of that stuff in the __init__() method:
class Poker(object):
def __init__(self, user_input=HandRange()):
self.user_input = user_input
self.translation = Translation.translateList(user_input)
self.evaluator = Evaluator.getEquities(x)
# and so on...
p = Poker()
# etc, etc...
This question is in continuation to my previous question, in which I asked about passing around an ElementTree.
I need to read the XML files only and to solve this, I decided to create a global ElementTree and then parse it wherever required.
My question is:
Is this an acceptable practice? I heard global variables are bad. If I don't make it global, I was suggested to make a class. But do I really need to create a class? What benefits would I have from that approach. Note that I would be handling only one ElementTree instance per run, the operations are read-only. If I don't use a class, how and where do I declare that ElementTree so that it available globally? (Note that I would be importing this module)
Please answer this question in the respect that I am a beginner to development, and at this stage I can't figure out whether to use a class or just go with the functional style programming approach.
There are a few reasons that global variables are bad. First, it gets you in the habit of declaring global variables which is not good practice, though in some cases globals make sense -- PI, for instance. Globals also create problems when you on purpose or accidentally re-use the name locally. Or worse, when you think you're using the name locally but in reality you're assigning a new value to the global variable. This particular problem is language dependent, and python handles it differently in different cases.
class A:
def __init__(self):
self.name = 'hi'
x = 3
a = A()
def foo():
a.name = 'Bedevere'
x = 9
foo()
print x, a.name #outputs 3 Bedevere
The benefit of creating a class and passing your class around is you will get a defined, constant behavior, especially since you should be calling class methods, which operate on the class itself.
class Knights:
def __init__(self, name='Bedevere'):
self.name = name
def knight(self):
self.name = 'Sir ' + self.name
def speak(self):
print self.name + ":", "Run away!"
class FerociousRabbit:
def __init__(self):
self.death = "awaits you with sharp pointy teeth!"
def speak(self):
print "Squeeeeeeee!"
def cave(thing):
thing.speak()
if isinstance(thing, Knights):
thing.knight()
def scene():
k = Knights()
k2 = Knights('Launcelot')
b = FerociousRabbit()
for i in (b, k, k2):
cave(i)
This example illustrates a few good principles. First, the strength of python when calling functions - FerociousRabbit and Knights are two different classes but they have the same function speak(). In other languages, in order to do something like this, they would at least have to have the same base class. The reason you would want to do this is it allows you to write a function (cave) that can operate on any class that has a 'speak()' method. You could create any other method and pass it to the cave function:
class Tim:
def speak(self):
print "Death awaits you with sharp pointy teeth!"
So in your case, when dealing with an elementTree, say sometime down the road you need to also start parsing an apache log. Well if you're doing purely functional program you're basically hosed. You can modify and extend your current program, but if you wrote your functions well, you could just add a new class to the mix and (technically) everything will be peachy keen.
Pragmatically, is your code expected to grow? Even though people herald OOP as the right way, I found that sometimes it's better to weigh cost:benefit(s) whenever you refactor a piece of code. If you are looking to grow this, then OOP is a better option in that you can extend and customise any future use case, while saving yourself from unnecessary time wasted in code maintenance. Otherwise, if it ain't broken, don't fix it, IMHO.
I generally find myself regretting it when I give in to the temptation to give a module, for example, a load_file() method that sets a global that the module's other functions can then use to find the file they're supposed to be talking about. It makes testing far more difficult, for example, and as soon as I need two XML files there is a problem. Plus, every single function needs to check whether the file's there and give an error if it's not.
If I want to be functional, I simply therefore have every function take the XML file as an argument.
If I want to be object oriented, I'll have a MyXMLFile class whose methods can just look at self.xmlfile or whatever.
The two approaches are more or less equivalent when there's just one single thing, like a file, to be passed around; but when the number of things in the "state" becomes larger than a few, then I find classes simpler because I can stick all of those things in the class.
(Am I answering your question? I'm still a big vague on what kind of answer you want.)