So I have a bunch of particles which can be of two kinds let's say "up" and "down". I am new to python but I know that this segregation can be done with the help of a class.
Let's say I have a list:
T=np.linspace(0,1,1000)
I want each element of this list to be either one of the two particles but I am not sure if I should create two classes with one "kind" each or a single class with two "instances" and assign each element an instance.
In the end, what I want to do is randomly distribute this property of being "up" and "down" over the list T.
There is not enough info. You most likely don't want 2 instances when dealing with 1000 items - each item should be probably represented by separate instance of a class. But that doesn't mean that having 2 classes is a way to go.
Are the particles relatively similiar and besides the difference of a single property they have the same behaviour? If so, I'd go for single class, 1000 instances and storing the up/down property in some instance attribute.
EDIT:
This is how I would personally implement this with for the current requirements in question:
class Particle:
def __init__(self, posInit, momInit, spin):
self.posInit = posInit
self.momInit = momInit
self.spin = spin
def momOfT(self, t):
return self.momInit*(math.cos(t))+self.posInit*(math.sin(t))
def posOfT(self, t):
return self.posInit*(math.cos(t))-self.momInit*(math.sin(t))
T = [Particle(posInit = i, momInit = 1-i, spin = random.choice(["up", "down"])) for i in np.linspace(0, 1, 1001)]
print([T[0].posOfT(i) for i in np.linspace(0, 3.1415*2, 1000)])
Related
I am new to Python and I run into a problem.
To keep it simple instead of sending you all my code I will generalize it a bit.
I want to create a class "object" with an x and y coordinate.
class Object():
def __init__(self, x, y):
self.x = x
self.y = y
object_1 = Object(0,0)
object_2 = Object(20, 20)
object_3 = Object(100, 100)
I created three objects of class Object(), each with an individual x and y coordinate. Now I want to add e.g. 5 to all three x coordinate without typing it manually. Is there a smarter way to add 5 to all members of this class?
i am sorry in case my question was answered in another post but I could find anything that helps me. Thank you in advance
To avoid doing it individually, do it in group, you could build a static method in the class that adds a value to the x of all given objects
#staticmethod
def addX(value, *items):
for item in items:
item.x += value
# call
Object.addX(5, object_1, object_2, object_3)
Code Demo
Save all of your obstacles in a list when you create them, something like a group.
You can save them in a list or save them inside another class that they are related to.
Then in each desired move execute a loop over that list, something like this:
for obstacle in obstacles:
obstacle.x += 5
I have created a class and am attempting to create a function that will, in essence, act as a binary operator between two objects of that class. The function I was trying to create is called 'combine'.
I know I could create the function outside of the class, but I want it to be associated with the class.
Background (not really necessary for answering the question) - the class is modelling the S4 mathematical group and is some practice with objects and classes for me. My next function was to be to simplify an element into it's simplest expression in cycles, which I am confident that I could do, but I would rather get this one sorted first.
When I create a function with one argument, it runs fine - as demonstrated in the code below, with the function 'cycletype', which works as expected.
class s4:
# Define an element of s4, elementlist is a nested list, which is a list of the cycles composing the element.
def __init__(self, elementlist):
self.elementlist = elementlist
# One simple function is to ascertain the cycletype of the element.
def cycletype(self):
cycles = []
for i in self.elementlist:
cycles.append(len(i))
return cycles
# Combining two elements using the group operation is the first function to define.
def combine(first, second):
for i in second:
first.append(i)
return first
double = s4([[1,2],[3,4]])
triple = s4([[1,2,3]])
print(combine(double,triple))
I was expecting [[1,2],[3,4],[1,2,3]] to be printed, however, it showed a NameError, not recognising combine.
You should be creating a new instance from the lists wrapped by the two arguments:
class S4:
# Define an element of S4, elementlist is a nested list, which is a list of the cycles composing the element.
def __init__(self, elementlist):
self.elementlist = elementlist
# One simple function is to ascertain the cycletype of the element.
def cycletype(self):
cycles = []
for i in self.elementlist:
cycles.append(len(i))
return cycles
# Combining two elements using the group operation is the first function to define.
def combine(self, first, second):
return S4(first.element_list + second.element_list)
It also appears that you could simply define __add__ instead of combine,
# Simplified implementation, no error checking
def __add__(self, second):
return S4(self.element_list + second.element_list)
allowing you to write
print(double + triple)
instead of
print(combine(double, triple))
There's two problems with the code
putting the function inside the class means that it's a method. So, you have to access it using the object s4.combine(s1), not just combine(...). Otherwise, it would be a function, not a method.
After you change that: you can't write for i in second, because instances of your class are not iterable. You have to implement __iter__ to be able to use that syntax
This is because the combine function isn't present in the global scope ( I hope that's what its called, I mess up names real bad).
You can only call functions present in the global scope, in the case of classes, you need objects to call these functions as these functions are part of those specific classes and not the global scope in general.
Hope this helped
There's a scope problem, you defined combine within the s4 class, so you should call it from a instance of s4. Anyways, here's is how I would do it.
class s4:
# Define an element of s4, elementlist is a nested list, which is a list of the cycles composing the element.
def __init__(self, elementlist):
self.elementlist = elementlist
# One simple function is to ascertain the cycletype of the element.
def cycletype(self):
cycles = []
for i in self.elementlist:
cycles.append(len(i))
return cycles
# Combining two elements using the group operation is the first function to define.
def combine(self, second):
#Here I changed first to self, first would be the s4 class that calls the function, in this example double and second would be the one that you want to combine
first = self.elementlist
for i in second.elementlist:
first.append(i)
return first
double = s4([[1,2],[3,4]])
triple = s4([[1,2,3]])
##As double() is defined within the s4 class, you can only call it from an instance of s4 (in this case you could use doble.combine() or triple.combine())
print(double.combine(triple))
Hope it helps.
I am trying to create a list within a class and then declaring elements in that list.
I don't even know if this is the right way for python. I have some java background.
I didn't add 10 elements in the list manually because I feel creating a dynamic list will be more useful.
class Levels:
def __init__(self):
self.type = "A"
self.size = [] # trying to create a list for 10 elements.
self.makespace(self.size) # running this method to create 10 spaces and then declare them.
def makespace(self, size):
for i in range(0,10):
if(size[i] == None):
size[i] = "free"
print(i)
else:
print("Didn't work")
print(i)
test = Levels()
Your problem lies in here.
if(size[i] == None):
size[i] = "free"
print(i)
At this moment, size is empty, it doesn't contain any elements so why are you
checking size[i] == None?
You probably think that a python list behaves like an array in Java where it initializes everything with null? Even though here you are not declaring the size of the list inside the init constructor, so I'm curious how you thought of that.
Your code should look like this:
class Levels:
def __init__(self):
self.type = "A"
self.size = [] # trying to create a list for 10 elements.
self.makespace(self.size) # running this method to create 10 spaces and then declare them.
def makespace(self, size):
#This will fill the emty list with 10 None(null) values
for i in range(0,10):
size.append(None)
test = Levels()
Also a bonus:
class Levels:
def __init__(self):
self.type = "A"
self.size = []
#Notice that I'm not passing self as an argument when I call makespace()
self.makespace()
def makespace(self):
#This will fill the emty list with 10 None(null) values
for i in range(0,10):
self.size.append(None)
test = Levels()
Self is the this keyword in python, the difference is that in Python you need to pass it as an argument only when declaring methods, not when you call them and also you can name it whatever you want!
Hope this helps!
This code won't work because size[i] does not exist. Instead use size.append(...). Also you should pass a number to makespace so that you can make space for an arbitrary number of items.
class Levels:
def __init__(self, kind='A', size=10):
self.kind = kind
self.size = [ 0 for _ in range(10) ]
These slight changes make your code more robust and more pythonic.
First but the least important is that type is a builtin-method (also a class and also a type) so kind is often substituted.
Second You can pass default arguments to the constructor (or any function) as you should generally avoid having constants inside functions like that. Here you can arbitrarily set a Level's kind, as well as the initial space required.
Third Using list-comprehension you can create a list of arbitrary size (or elements). The syntax is
[ expression for args in iterable ]
which allows for any expression to be generated based on arguments passed from an iterable. Read more about list comprehension and other datastructure here.
As for your makespace you shouldnt really need it, however you could change the implementation so you can allocate more space (using self.size.append(...)) or overwriting currently used space.
Best of luck!
If you want to have 10 free spaces in the list upon initializing, change
self.size = []
to
self.size = [“free”] * 10
If you want to start with an empty list and add 10 free spaces in your makespace loop, simply use
self.size.append(“free”)
Also, you really don’t need to pass size to makespace. Since you’re already passing self, I would just reference self.size from inside the makespace function.
I have class for calculating temperatures of an object at different positions, based on ambient temperature. I have two ways of implementation. In BodyA, the temperature of each position is an attribute of the class; while in BodyB, there is an attribute pos_t, which is a dict, and the temperature of each position is just a key-value pair in the dict.
class BodyA:
def __init__(self, ambient_temperature)
self.amb_t = ambient_temperature
self.pos1_t = self.amb_t + 1
self.pos2_t = self.amb_t * 2
self.pos3_t = self.pos1_t + self.pos2_t - 5
class BodyB:
def __init__(self, ambient_temperature)
self.amb_t = ambient_temperature
self.pos_t = dict()
self.pos_t['pos1'] = self.amb_t + 1
self.pos_t['pos2'] = self.amb_t * 2
self.pos_t['pos3'] = self.pos_t['pos1'] + self.pos_t['pos2'] - 5
In practical case, there are up-to 10 positions, and I want to build child-class from it. And some child-classes do not have certain positions. For example, pos2 can be missing in some child.
Could you please let me know, which design is better in terms of OOP and efficiency. Thanks.
A data structure to store some custom identifiers that may or may exist calls clearly for a dict. As class attributes are also stored in an internal dict, the first approach can be used too, but to have pratical manipulation without explicit hand writing the members will require different code. I suspect performance will not matter. If you find it matters, maybe a redesign of the data structure that does not use classes at all will do, as object creation processing time may be relevant then.
Using python.....I have a list that contain names. I want to use each item in the list to create instances of a class. I can't use these items in their current condition (they're strings). Does anyone know how to do this in a loop.
class trap(movevariables):
def __init__(self):
movevariables.__init__(self)
if self.X==0:
self.X=input('Move Distance(mm) ')
if self.Vmax==0:
self.Vmax=input('Max Velocity? (mm/s) ')
if self.A==0:
percentg=input('Acceleration as decimal percent of g' )
self.A=percentg*9806.65
self.Xmin=((self.Vmax**2)/(2*self.A))
self.calc()
def calc(self):
if (self.X/2)>self.Xmin:
self.ta=2*((self.Vmax)/self.A) # to reach maximum velocity, the move is a symetrical trapezoid and the (acceleration time*2) is used
self.halfta=self.ta/2. # to calculate the total amount of time consumed by acceleration and deceleration
self.xa=.5*self.A*(self.halfta)**2
else: # If the move is not a trap, MaxV is not reached and the acceleration time is set to zero for subsequent calculations
self.ta=0
if (self.X/2)<self.Xmin:
self.tva=(self.X/self.A)**.5
self.halftva=self.tva/2
self.Vtriang=self.A*self.halftva
else:
self.tva=0
if (self.X/2)>self.Xmin:
self.tvc=(self.X-2*self.Xmin)/(self.Vmax) # calculate the Constant velocity time if you DO get to it
else:
self.tvc=0
self.t=(self.ta+self.tva+self.tvc)
print self
I'm a mechanical engineer. The trap class describes a motion profile that is common throughout the design of our machinery. There are many independent axes (trap classes) in our equipment so I need to distinguish between them by creating unique instances. The trap class inherits from movevariables many getter/setter functions structured as properties. In this way I can edit the variables by using the instance names. I'm thinking that I can initialize many machine axes at once by looping through the list instead of typing each one.
You could use a dict, like:
classes = {"foo" : foo, "bar" : bar}
then you could do:
myvar = classes[somestring]()
this way you'll have to initialize and keep the dict, but will have control on which classes can be created.
The getattr approach seems right, a bit more detail:
def forname(modname, classname):
''' Returns a class of "classname" from module "modname". '''
module = __import__(modname)
classobj = getattr(module, classname)
return classobj
From a blog post by Ben Snider.
If it a list of classes in a string form you can:
classes = ['foo', 'bar']
for class in classes:
obj = eval(class)
and to create an instance you simply do this:
instance = obj(arg1, arg2, arg3)
EDIT
If you want to create several instances of the class trap, here is what to do:
namelist=['lane1', 'lane2']
traps = dict((name, trap()) for name in namelist)
That will create a dictionary that maps each name to the instance.
Then to access each instance by name you do:
traps['lane1'].Vmax
you're probably looking for getattr.