Lateral association between an object and a function assigned to variable - python

I have objects defined that are evolving under a subroutine, and under subsubroutines. And I want to probe the status of these variables via probes.
For example, lets call this class drunk.
class drunk (object):
def __init__(self):
self.position = 0
self.probability = 0.5
def take_a_step():
# code that will make the drunkard change its position
Then, I may generate many drunkards and put them into a class crowd.
class crowd (object):
def __init__(self):
self.inidividuals = num.array([])
I would like to create a "probe" object that can be assigned into any of those objects, but I have implementation problems.
class probe (object):
def __init__(self):
self.function = None
self.data = num.array([])
I want to assign probes to any drunkard, a probe will extract any information from a crowd, or a drunk, that is defined in a function residing in probe.function.
But as far as I am concerned, I can assign probes by putting them into a list within these classes, and call them by relating to the functions within the methods of the classes crowd and drunk.
But in order to do this,
probe_mean = probe()
def probe_function():
#
#
#
probe_mean.function = probe_function()
But since I want to refer to a variable within a class that the function will be within the list of, It seems that I must define the function as
But in order to do this,
probe_mean = probe()
def probe_function(probed):
return probed.position.mean()
probe_mean.function = probe_function(drunk_53)
drunk_53.probes.append(probe_mean)
I have a feeling from the fact that these to objects should refer to each other in order for this to work, this is not he way it should be.
I thought that there must be a way to deal with this without re-introducing drunk_53 to the function, something like a super(), that will enable a vertical association.
I'm not experienced in OOP, so I'm asking for the most suitable way (Pythonic, elegant etc.) to do this. What are your opinions? What approach would you take?

Related

Best Practice in Python: Class Object with helper variables - delete helpers after use

I want to have a Class with only one argument to it. Based on that argument a couple of calculations should take place aiming at setting a specific attribute for the Class. Other attributes won't be needed afterwards and I would like to delete them within the Class. What's the best approach?
Simplified Example:
class Sportsteam:
def __init__(self, members):
self.members = members # members will be a list
self.num_members = len(self.members) # helpler variable: how many team members are in the sportsteam?
self.rooms = math.ceil(self.num_members/2) # how many doubles will be needed in a hotel?
I want to delete the instance variable num_members because it won't be needed afterwards. I want that to be done within the class/object, so I do not need a separate line with del instance.num_members within my script for each instance.
Please note that variable assigning is more complex with a lot of conditions in the original use case. Calculation without the helper-variable would work in the example above, but would be really annoying in the use case.
As #monk pointed out, also local variables can be assigned within the __init__ statement. For above example the use of a helper variable would therefor be:
class Sportsteam:
def __init__(self, members):
self.members = members # members will be a list
num_members = len(self.members) # helper variable: how many team members are in the sportsteam?
self.rooms = math.ceil(num_members/2) # how many doubles will be needed in a hotel?
In this case instance.num_members does not exist.
I was researching for an answer to my question with different keywords for quite a while, but neither came to a solution nor to an example which showed that possibility

How to get the value of a variable of one class in another class without using inheritance and without initialsing init?

I have Pyhton classes A and B. I want to access the value of x in class B.
class A():
def __init__(self):
self.x = 0
def do(self):
self.x = 1 + 2
class B():
#get the value of x which is 3, not 0.
How do I do this? If I create an instance, init is called which re-initializes x to 0, but I want the final value of x which is 3.
Does anyone please have a solution?
Avoiding dependencies between classes is an important principle of OOP which should not be violated lightly. To the extent that classes need to interchange information, this should happen via public and documented methods.
Python doesn't enforce this, but you should probably be looking for a different way to address whichever problem you hope to solve with this arrangement.
The class A doesn't have any x which exists in the class itself; the way you have defined the class, x is an instance attribute. It is only defined when you have an object which belongs to the class, and each object instance has a value for this variable which is separate from every other instance's. The class itself doesn't have a variable with this name.
Perhaps you are really looking for a class attribute, something like this?
class A():
x = None
def __init__(self):
if self.__class__.x is None:
self.__class__.x = 0
def do(self):
self.__class__.x = 3
#classmethod
def _get_x(cls):
return cls.x
class B():
:
value_of_A_x = A._get_x()
The leading underscore in the name of the class method _get_x informally suggests that this is a private method.
You'll notice that x has three states. It starts out as None, then when the first instance of an A object is created, it gets set to 0. The first time an instance's do method is called, it gets set to 3. There are currently no other ways to change its value, though you are of course free to change this code or add new code in accordance with your requirements.
The above is highly speculative, but should at the very least help you write a better question by explaining what you actually want to achieve. Code which doesn't work at all is not a good way to tell us what you actually want.

Accessing instance variable from other instance in python

I am trying to find the best way of accessing an instance variable from another instance. So far I've been able to pass that variable as an argument and save it in the new instance. But I am wondering if there is some sort of "Global" variable that will work best. Specially if the classes are from different modules.
Here is my example:
class A(object):
def __init__(self):
self.globalObject = "Global Object"
self.listB = self.generateBList()
def generateBList(self):
return [B(self.globalObject, i) for i in range(10)]
class B(object):
def __init__(self, globalObject, index):
self.index = index
self.globalObject = globalObject
def splitGlobalObject(self):
return self.globalObject.split(" ")
a = A()
firstB = a.listB[0]
print firstB.splitGlobalObject()
Here when I generateBList() I need to pass always that globalObject as an argument B(self.globalObject, i), and then this object gets saved into B.globalObject, butif i had many classes that needed to access that global object im not sure if passing it always as an argument would be the best option. What would be the best way of accessing it without having to pass it always as an argument when you create instances?
I hope I explained my way properly.
Your example seems unnecessarily complicated, so I'll try to illustrate one way I've used before that I think may do what you want. If you think of creating a "world" that is the stage for what you want to happen, you can have each class instance inside the world, know the world. Like this:
class Thing(object):
def __init__self(self, world, name):
self.world = world
self.name = name
class Word(object):
def __init__(self):
self.everyone = [Thing(self, i) for i in range(10)]
if __name__ == '__main__':
world = World()
In this example, the World class instance carries around an attribute called everyone that is a list of ten Thing objects. More importantly for your example, each instance of Thing now carries around a pointer called self.world that points to the world class. So all Things can access all other Things via self.world.everyone, as well as anything else in the world. I also passed i into each Things init so they have a unique name in the form of an integer between 0 and 9, but that may be extra for what you need.
From here there's basically nothing that your instances can't do to each other via methods, and all without using lots of globals.
Edit: I should add that being from different modules will make no difference here, just import as many as you want and create instances of them that pass knowledge of the World instance into them. Or obviously tailor the structure to your needs while using the same idea.
It's possible to use global variables in python.
class A(object):
def __init__(self):
global globalObject
globalObject = "Global Object"
self.listB = self.generateBList()
def generateBList(self):
return [B(i) for i in range(10)]
class B(object):
def __init__(self, index):
self.index = index
def splitGlobalObject(self):
return globalObject.split(" ")
Usually you want to avoid globals. Visit http://www.python-kurs.eu/python3_global_lokal.php for more examples.

Avoid putting "global" in every single function

Python is supposed to be fun, simple and easy to learn.
Instead, it's been a huge pain.
I've discovered that all the errors I'm getting are related to me not declaring each variable global in each function.
So for my toy program of dressUp, I have to write:
hatColor = ""
shirtColor = ""
pantsColor = ""
def pickWardrobe(hat, shirt, pants):
global hatColor
global shirtColor
global pantsColor
...
This gets really annoying when I have 20 functions, and each one needs to have 20 global declarations at the beginning.
Is there any way to avoid this?
Thanks!
ADDED
I am getting tons of `UnboundLocalError - local variable X referenced before assignment.
Why am I doing this? Because I need to write a py file that can do some calculations for me. I don't want it all in the same function, or it gets messy and I can't reuse code. But if I split the work among a few functions, I have to declare these annoying globals over and over.
Classes versus global variables
global is common to all
class is a template for an object, representing something, here it could be person dressed up somehow.
Class might have class properties, these are not so commonly used, as they are shared by all instances (sort of "global for classes).
Classes start living as soon as you instantiate them, it means, the pattern defined by class definition is realized in form of unique object.
Such an object, called instance, might have it's own properties, which are not shared with other instances.
I am sometime thinking about a class as of a can - class definition means "can is something you can put thing into" and instance is real tangible can, which has a name of it and in Python I put property values into it, which are bound to the name of given can holder.
DressUp class with real instance properties
Properties in "holmeswatson" solution are bound to class definition. You would run into problems if you would use multiple instances of DressUp, they would be sharing the properties over class definition.
It is better and safer to use it as instance variables, which are over self bound to instance of the class, not to class definition.
Modified code:
class DressUp:
def __init__(self, name, hatColor="", shirtColor=""):
self.name = name
self.hatColor = hatColor
self.shirtColor = shirtColor
def pickWardrobe(self,hat, shirt):
self.hatColor = hat
self.shirtColor = shirt
def __repr__(self):
name = self.name
hatColor = self.hatColor
shirtColor = self.shirtColor
templ = "<Person:{name}: hat:{hatColor}, shirt:{shirtColor}>"
return templ.format(name=name, hatColor=hatColor, shirtColor=shirtColor)
tom = DressUp("Tom")
tom.pickWardrobe("red","yellow")
print "tom's hat is", tom.hatColor
print "simple print:", tom
print "__repr__ call:", tom.__repr__()
jane = DressUp("Jane")
jane.pickWardrobe("pink","pink")
print "jane's hat is", jane.hatColor
print "simple print:", jane
print "__repr__ call:", jane.__repr__()
The __repr__ method is used at the moment, you call print tom or print jane.
It is used here to show, how to instance method can get access to instance properties.
Is there any way around it? Yes, there are several. If you're using global variables on a regular basis, you're making a mistake in your design.
One common pattern when you have many functions that will operate on the same, related data is to create a class and then declare instances of that class. Each instance has its own set of data and methods, and the methods within that instance can operate on the data within that instance.
This is called object oriented programming, it is a common and basic paradigm in modern programming.
Several respondents have sketched out what a class might look like in your case but I don't think you've given enough information (which would include the method signatures of the other functions) to actually write out what you need. If you post more information you might get some better examples.
If it is appropriate, you could use classes.
class DressUp:
def __init__(self, name):
self.name = name
def pickWardrobe(self,hat, shirt, pants):
self.hatColor = hat
self.shirtColor = shirt
self.pantsColor = pants
obj1 = DressUp("Tom")
obj1.pickWardrobe("red","yellow","blue")
print obj1.hatColor
Have a look:
http://www.tutorialspoint.com/python/python_classes_objects.htm

best practise to init member

I have a question on best practises to initialise a class. Consider a class that is complex and has a lot of members. It's bad practise to init them outside of __init__(), but how can I handle the problem without having an enormous __init__() method.
An example:
class A:
def __init__(self):
self.member0 = "a"
# to prevent that the init method gets too big
# put some initialisation outside
init_other_stuff()
def init_other_stuff(self):
self.member1 = "b"
self.member2 = "c"
...
Thanks in advance.
[update] To clarify. The goal is not to put the stuff into another long method of course. Instead you can split the initialisation into different parts like:
def init_network_stuff(self):
""" init network setup """
self.my_new_socket = socket.socket(..)
def init_local_stuff(self):
""" init local setup """
self.my_new_logpath = "/foo/bar/log"
...
I would also agree that having too many attributes is probably a sign of insufficient abstraction, which is usually harder to develop & debug, and so changing your design is probably a good idea.
But, you do have a gold badge, so you've obviously been around and (probably) know what you are doing, and might have a reason to do this. In that case, I think it's a good idea to split up the initialization by category like you suggested. The only suggestion I would have is to use _ on the sub-init functions to signal to a user they aren't intended for normal use i.e.
class A:
def __init__(self):
self.member0 = "a"
self.__init_other_stuff()
def __init_other_stuff(self):
self.member1 = "b"
self.member2 = "c"
etc. This also hides them from tab-completion in most consoles & editors.
Your other choice is to make this class a subclass of multiple classes that implement part of the interface if you really need A to contain those items directly, i.e. do something like this:
class Logger(object):
def __init__(self):
self.logparam = 1
class NetworkSource(object):
def __init__(self):
self.netparam = 2
class A(Logger, NetworkSource):
def __init__(self):
Logger.__init__(self)
NetworkSource.__init__(self)
In [2]: a = A()
In [3]: a.<tab>
a.logparam a.netparam
Then it would get the functionality of both classes, while having a relatively short init. Multiple inheritance is conceptually a little more complicated though IMHO.

Categories

Resources