global methods or functions in python - python

I am making a small game in Python using pythonista on my ipad.
I made a vector class that contains the coordinates and several functions to add, get a length, set a length. I have another class called Game in which I have my game variables and functions. I can define a vector lets say
self.pos=vector(200,200)
But if I want to work out the length, I can't call the getlength function because I'm not in the right class.
Example (I've taken out most of the code):
class vector(objet):
def __init(self,x,y):
self.x=x
self.y=y
def getlength(self):
return sqrt(self.x**2+self.y**2)
def addvec(self,a,b):
return vector(a.x+b.x,a.y,b.y)
class Game(object):
def __init__(self):
self.pos=vector(200,200)
self.pos=vector(200,200)
def loop(self):
## here i want something like d= length of self.pos !!
class MyScene(Scene):
def setup(self):
self.game=Game()
def draw(self):
self.game.loop()
run(MyScene())
Thanks,
Nicolas
EDIT : the call
sum=addvec(self.pos,self.pos2)
obviously doesn't work because self is a Game class. How can I do it?

Why do you use two arguments for the getLength function? The second one is a vector (I assume) so it would be better to use:
def getLength(self):
return sqrt(self.x**2+self.y**2)
and then just call:
d = self.pos.getLength()
If you would want to add two vectors together you would do something like this:
def add(self,other_vector):
return vector(self.x+other_vector.x,self.y+other_vector.y)
so you would call:
sum = self.pos.add(some_other_vector)
BTW: Classes should always be written in CamelCase. And maybe you should read something about object oriented programming in python: http://code.tutsplus.com/articles/python-from-scratch-object-oriented-programming--net-21476

Related

self in Python classes

I know first argument in Python methods will be an instance of this class. So we need use "self" as first argument in methods. But should we also specify attribures (variables) in method starting with "self."?
My method work even if i don't specify self in his attributes:
class Test:
def y(self, x):
c = x + 3
print(c)
t = Test()
t.y(2)
5
and
class Test:
def y(self, x):
self.c = x + 3
print(self.c)
t = Test()
t.y(2)
5
For what i would need specify an attribute in methods like "self.a" instead of just "a"?
In which cases first example will not work but second will? Want to see situation which shows really differences between two of them, because now they behave the same from my point of view.
The reason you do self.attribute_name in a class method is to perform computation on that instances attribute as opposed to using a random variable.For Example
class Car:
def __init__(self,size):
self.size = size
def can_accomodate(self,number_of_people):
return self.size> number_of_people
def change_size(self,new_size):
self.size=new_size
#works but bad practice
def can_accomodate_v2(self,size,number_of_people):
return size> number_of_people
c = Car(5)
print(c.can_accomodate(2))
print(c.can_accomodate_v2(4,2))
In the above example you can see that the can_accomodate use's self.size while can_accomodate_v2 passes the size variable which is bad practice.Both will work but the v2 is a bad practice and should not be used.You can pass argument into a class method not related to the instance/class for example "number_of_people" in can_accomodate funtion.
Hope this helps.

Using Python Factory Idioms

Below is a pattern from :https://python-3-patterns-idioms-test.readthedocs.io/en/latest/Factory.html . My question is this, is this still the best idiom/pattern to do generic object creation in Python 3.x? I can't seem to find much on this topic. The code is below:
class Shape(object):
# Create based on class name:
def factory(type):
#return eval(type + "()")
if type == "Circle": return Circle()
if type == "Square": return Square()
assert 0, "Bad shape creation: " + type
factory = staticmethod(factory)
class Circle(Shape):
def draw(self): print("Circle.draw")
def erase(self): print("Circle.erase")
class Square(Shape):
def draw(self): print("Square.draw")
def erase(self): print("Square.erase")
# Generate shape name strings:
def shapeNameGen(n):
types = Shape.__subclasses__()
for i in range(n):
yield random.choice(types).__name__
shapes = \
[ Shape.factory(i) for i in shapeNameGen(7)]
for shape in shapes:
shape.draw()
shape.erase()
You can also create a factory by using the __class__ method as well I've noticed, but I'm unsure of the best way to use this.
I could be missing something, but I don't like this pattern.
You already have factories for Circle and Square - Circle and Square. :)
The code in your question unnecessarily hardcodes the class names in factory and then goes through some extra hoops by getting the names of the subclasses of Shape and then calling factory with those names.
A more direct way to generate the shapes list is
types = Shape.__subclasses__()
shapes = [random.choice(types)() for _ in range(7)]
I have a situation where I could have multiple geometries being given. This is an over simplified example, but I am getting JSON response of various geometries, and instead of having to write multiple if statements multiple times, I thought using a Factory could reduce the issue: so Shape(JSON) -> Circle or Shape(JSON) - Square
This does not justify the factory as it is coded here. You could have a simple dictionary like
classes = {'Circle': Circle, 'Square': Square, ...}
or possibly create it dynamically with
classes = {cls.__name__:cls for cls in Shape.__subclasses__()}
and then call classes[some_string]() for the instantiation. You can even dynamically instantiate a class by string name using getattr.

Return values automatically in python class

I am a new python user. Thus it might be very silly. But what is the best way to run a class automatically (which has several functions inside) and return the result for a given value. for example:
class MyClass():
def __init__(self,x):
self.x=x
def funct1(self):
return (self.x)**2
##or any other function
def funct2(self,y):
return y/100.0
##or any other function
def wrapper(self):
y=self.funct1()
z=self.funct2(y)
##or other combination of functions
return z
Right now to run this, I am using:
run=MyClass(5)
run.wrapper()
But I want to run like this:
MyClass(5)
Which will return a value and can be saved inside a variable with out needing to use the wrapper function.
You can create a functor as below:
class MyClass(object):
def __init__(self,x):
self.x=x
def funct1(self):
return (self.x)**2
##or any other function
def funct2(self,y):
return y/100.0
##or any other function
def __call__(self):
y=self.funct1()
z=self.funct2(y)
##or other combination of functions
return z
The call to this functor will be like as follow:
MyClass(5)() # Second () will call the method __call__. and first one will call constructor
Hope this will help you.
So when you write MyClass(5), you're instatiating a new instance of that class: MyClass and so the short answer is no, you do need the wrapper because when you instantiate the class it will necessarily return the object and not a certain value.
If you want to just return a value based on the input (say 5) consider using a function instead.
The function would be like:
def my_func(x):
y = x**2
z = y/100.0
return z
There a lots of reasons to use classes, see this answer https://stackoverflow.com/a/33072722/4443226 -- but if you're just concerned with the output of an operation/equation/function then I'd stick with functions.
__init__ method should return None.
documentation link
no non-None value may be returned by init()

Inheritance of from_<type> in Python

Edit: There was some confusion, but I want to ask a general question about object oriented design in Python.
Consider a class that lets you map data values to counts or frequencies:
class DataMap(dict):
pass
Now consider a subclass that allows you to construct a histogram from a list of data:
class Histogram(DataMap):
def __init__(self, list_of_values):
# 1. Put appropriate super(...) call here if necessary
# 2. Build the map of values to counts in self
pass
Now consider a class that lets you make a smoothed probability mass table rather than a Histogram.
class ProbabilityMass(DataMap):
pass
What is the best way to allow a ProbabilityMass to be constructed from either a Histogram or a list of values?
I "grew up" programming in C++, and in this case I would use an overloaded constructor. In Python I've thought of doing this with:
The constructor takes multiple arguments (all but one of these should == None)
I define from_Histogram and from_list methods
In the second case (which I believe is better), what is the best way to allow the from_list method to use the shared code from the Histogram constructor? A ProbabilityMass table is nearly identical to a Histogram table, but it is scaled so that the sum of all value is 1.0.
If you have come across a similar problem, please share your expertise!
To start with, if you think you want #staticmethod, you almost always don't. Either the function is not part of the class, in which case it should just be a free function, or it is part of the class, but not tied to an instance, and it should be a #classmethod. Your named constructor is a good candidate for a #classmethod.
Also note that you should invoke A.__init__ from B via super(), otherwise multiple inheritance can bite you bad.
class A:
def __init__(self, data):
self.values_to_counts = {}
for val in data:
if val in self.values_to_counts:
self.values_to_counts[val] += 1
else:
self.values_to_counts[val] = 1
#classmethod
def from_values_to_counts(cls, values_to_counts):
self = cls([])
self.values_to_counts = values_to_counts
return self
class B(A):
def __init__(self, data, parameter):
super(B, self).__init__(data)
self.parameter = parameter
def print_parameter(self):
print self.parameter
In this case, you don't need a B.from_values_to_counts, it inherits from A, and it will return an instance of B, since that's how it was called.
If you need to do more complex initialization in B, you can, using super(), which looks very similar to the way it would when you use it with instances. after all, a classmethod really isn't anything more complex than an instancemethod where the im_self attribute is assigned to the class itself.
class A:
def __init__(self, data):
self.values_to_counts = {}
for val in data:
if val in self.values_to_counts:
self.values_to_counts[val] += 1
else:
self.values_to_counts[val] = 1
#classmethod
def from_values_to_counts(cls, values_to_counts):
self = cls([])
self.values_to_counts = values_to_counts
return self
class B(A):
def __init__(self, data, parameter):
super(B, self).__init__(data)
self.parameter = parameter
def print_parameter(self):
print self.parameter
#classmethod
def from_values_to_counts(cls, values_to_counts):
self = super(B, cls).from_values_to_counts(values_to_counts)
do_more_initialization(self)
return self

Understanding python variable scope within class

I am trying to define a variable in a class that then can be accessed/changed from functions within that class.
For example:
class MyFunctions():
def __init__( self):
self.listOfItems = []
def displayList( self):
"""Prints all items in listOfItems)"""
for item in self.listOfItems:
print item
def addToList(self):
"""Updates all mlb scores, and places results in a variable."""
self.listOfItems.append("test")
f = MyFunctions()
f.addToList
f.displayList
This should output all of the items in the list for me, but instead it displays nothing. I am assuming this is occuring because I did not setup the scope of the variables correctly. I want to be able to access and change listOfItems from within all of the functions in MyFuctions.
I have been trying to figure this out for a few hours now, so any help would be greatly appreciated.
f.addToList and f.displayList do not invoke the methods addToList and displayList respectively. They simply evaluate to the method (bound to the object f in this case) themselves. Add parentheses to invoke the methods as in the corrected version of the program:
class MyFunctions():
def __init__( self):
self.listOfItems = []
def displayList( self):
"""Prints all items in listOfItems)"""
for item in self.listOfItems:
print item
def addToList(self):
"""Updates all mlb scores, and places results in a variable."""
self.listOfItems.append("test")
f = MyFunctions()
f.addToList()
f.displayList()
This is in contrast to Ruby which does not require parentheses for method invocation (except to eliminate ambiguity in certain cases).
It is instructive to add the following to the end of your program:
print type(f.addToList)
This will output something like the following:
<type 'instancemethod'>
demonstrating that this is a method reference and not a method invocation.

Categories