Placing custom class object in a list - python

I'm fairly new to object oriented programming so some of the abstraction ideas are a little blurry to me. I'm writing an interpreter for an old game language. Part of this has made me need to implement custom types from said language and place them on a stack to be manipulated as needed.
Now, I can put a string on a list. I can put a number on a list, and I've even found I can put symbols on a list. But I'm a bit fuzzy on how I would put a custom object instance on a list when I can't just drop it into a variable (since, after all, I don't know how many there will be and can't go about defining them by hand while the code is running :)
I've made a class for one of the simplest data types-- a DBREF. The DBREF just contains a Database reference number. I can't just use an integer, string, dictionary, etc, because there are type-checking mechanisms in the language I have to implement and that would confuse matters, since those are already used elsewhere in their closes analogues.
Here is my code and my reasoning behind it:
class dbref:
dbnumber=0
def __init__(self, number):
global number
dbnumber=number
def getdbref:
global number
return number
I create a class named dbref. All it does (for now) is take a number and store it in a variable. My hope is that if I were to do:
examplelist=[ dbref(5) ]
That the dbref object would be on the stack. Is that possible? Further, will I be able to do:
if typeof(examplelist[0]) is dbref:
print "It's a DBREF."
else:
print "Nope."
...or am I misunderstanding how Python classes work? Also, is my class definition wonky in any way?

If you used...
class dbref:
dbnumber=0
that would share the same number among all instances of the class, because dbnumber would be a class attribute, rather than an instance attribute. Try this instead:
class dbref(object):
def __init__(self, number):
self.dbnumber = number
def getdbref(self):
return self.dbnumber
self is a reference to the object instance itself that's automatically passed by Python when you call one of the instance's methods.

Related

Is it possible to instantiate multiple instances of a class through a single classmethod call?

So I've used python as a functional language for a while but I'm trying to do thing "right" and use classes now... and falling down. I'm trying to write a classmethod that can instantiate multiple members of the class (use case is load rows from SQLAlchemy.) I'd like to just be able to call the classmethod and have it return a status code (success/failure) rather than returning a list of objects. Then to access the objects I'll iterate through the class. Here's my code so far (which fails to iterate when I use the classmethod, works fine when I use the normal constructor.) Am I way off-base/crazy here? What's the "pythonic" way to do this? Any help is appreciated and thank you.
class KeepRefs(object):
__refs__ = defaultdict(list)
def __init__(self):
self.__refs__[self.__class__].append(weakref.ref(self))
#classmethod
def get_instances(cls):
for inst_ref in cls.__refs__[cls]:
inst = inst_ref()
if inst is not None:
yield inst
class Credentials(KeepRefs):
def __init__(self,name, username, password):
super(Credentials, self).__init__()
self.name=name
self.username=username
self.password=password
#classmethod
def loadcreds(cls):
Credentials('customer1','bob','password')
return True
success = Credentials.loadcreds()
for i in Credentials.get_instances():
print (i.name)
In your own words - yes, you are off-base and crazy :)
Status-Codes are a thing of C, not languages with proper exception semantics as Python. Modifying global state is a sure recipe for disaster. So - don't do it. Return a list of objects. Throw an exception if something disastrous happens, and just return an empty list if there happen to be no objects. This allows the client code to just do
for item in Thingies.load_thingies():
... # this won't do anything if load_thingies gave us an empty list
without having to painstakingly check something before using it.
Functional languages have certain advantages, and you are going too far the other way in your exploration of the procedural style. Global variables and class variable have their place, but what will happen if you need to fire off two SQAlchemy queries and consume the results in parallels? The second query will stomp over the class attributes that the first one still needs, is what. Using an object attribute (instance attribute) solves the problem, since each result contains its own handle.
If your concern is to avoid pre-fetching the array of results, you are in luck because Python offers the perfect solution: Generators, which are basically lazy functions. They are so nicely integrated in Python, I bet you didn't know you've been using them with every for-loop you write.

Init in classes - is the first argument a stand in for the instance?

I have been trying to fully understand this for a while now, and practically speaking I think I understand what happens but I can't seem to find anywhere that confirms wether I understood it correctly:
class test(object):
def __init__(self, this):
self.something = this
example = test("writing")
My question is: In the above example, is it correct that self is simply a stand-in for the instance I am creating? Meaning that when i create an instance and assign it to "example", then "example is put in place of self and behind the scenes does something resembling this:
class test(object):
def __init__(example, this):
example.something = this
example = test("writing")
Furthermore, does that also mean that as long as I am still working with this on a class basis (say in tandem with another class) I should still be using self.something, while I should be using example.something if I am working with it on an instance level?
I hope that made somewhat sense, im still trying to wrap my head properly around all of it, so let me know if I need to try and rephrase it.
For reference sake, should someone else end up asking the same, this reply: Python __init__ and self what do they do? almost did the trick for me, and only really left me a bit in doubt about the above questions.
This is correct. self is the instance of the class (i.e. the object) and you use it inside the class code (inside it's methods).
While the first argument can be named something else (example in your second code), the convention is that we always use self or the code might be highly confusing for other programmers. But you got the gist right by doing that, the example variable in the class (i.e. the self in your first code) and the example variable outside of the class is basically the same thing.
By the way, I'd also avoid the following two things:
having a class name that starts with a small leter case,
using a variable name this (since a variable named this does in some other languages essentially what self does in Python).
In Python, variables do not "contain" objects, they refer to them. So:
class test(object):
def __init__(self, this):
self.something = this
example = test("writing")
In this case example is a reference to the new object, but so is self. It is perfectly legal, and common, to have multiple references to the same object.
If you did:
another = example
this would not create a new object but have another reference to the same object. another, example (and self) would be references to the same single object.
You can test this by looking at the object's unique identifier, using id(). Add:
another = example
print id(another)
print id(example)
you will find that their id's are the same.

Where is the best place to put support functions in a class?

In Python, I have a class that I've built.
However, there is one method where I apply a rather specific type of substring-search procedure. This procedure could be a standalone function by itself (it just requires a needle a haystack string), but it feels odd to have the function outside the class, because my class depends on it.
What is the typical design paradigm for this? Is it typical to just have myClassName.py with the main class, as well as all the support functions outside the class itself, in the same file? Or is it better to have the support function embedded within the class at the expense of modularity?
You can create a staticmethod, like so:
class yo:
#staticmethod
def say_hi():
print "Hi there!"
Then, you can do this:
>>> yo.say_hi()
Hi there!
>>> a = yo()
>>> a.say_hi()
Hi there!
They can be used non-statically, and statically (if that makes sense).
About where to put your functions...
If a method is required by a class, and it is appropriate for the method to perform data that is specific to the class, then make it a method. This is what you would want:
class yo:
self.message = "Hello there!"
def say_message(self):
print self.message
My say_message relies on the data that is particular to the instance of a class.
If you feel the need to have a function, in addition to the class method, by all means go ahead. Use whichever one is more appropriate in your script. There are many examples of this, including in the python built-ins. Take generator objects for example:
a = my_new_generator()
a.next()
Can also be done as:
a = my_new_generator()
next(a)
Use whichever is more appropriate, and obviously whichever one is more readable. :)
If you can think or any reason to override this function one day, make it a staticmethod, else a plain function is just ok - FWIW, your class probably depends on much more than this simple function. And if you cannot think of any reason for anyone else to ever use this function, keep it in the same module as your class.
As a side note: "myClassName.py" is definitly unpythonic. First because module names should be all_lower, then because the one-module-per-class stuff is a nonsense in Python - we group related classes and functions (and exceptions and whatnots) together.
If the search method you are talking about is really so specific and you will never need to reuse it somewhere else, I do not see any reason to make it static. The fact that it doesn't require access to instance variables doesn't make it static by definition.
If there is a possibility, that this method is going to be reused, refactor it into a helper/utility class (no static again).
ADDED:
Just wanted to add, that when you consider something being static or not, think about how method name relates to the class name. Does this method name makes more sense when used in class context or object context?

How to create a dynamically updating list of class instances, satisfying a particular condition? (Python)

I want to create a list of class instances that automatically updates itself following a particular condition on the instance attributes.
For example, I have a list of object of my custom class Person() and I want to be able to generate a list that always contains all the married persons, i.e. all persons having the attribute 'MAR_STATUS' equal to 'MARRIED'.
Is this possible at all in Python? I have used a C++ precompiler for microsimulations that had a very handy built-in called "actor_set" which did exactly this. But I have no idea of how it was implemented in C++.
Thank you.
List comprehension:
[person for person in people if person.MAR_STATUS == 'MARRIED']
If you need to assign it to a variable and you want that variable to automatically update on every access, you can put this same code in a lambda, a normal function, or, if your variable is a class member, in a property getter.
It is poor form to have "action at a distance" / mutations / side-effects unless it is very carefully controlled.
That said, imperative language will let you do this, if you really want to, as follows. Here we use python's [property getters and setters]:
MARRIED_SET = set()
def updateMarriedSet(changedPerson):
if hasattr(changedPerson,'married') and changedPerson.married==Person.MARRIED:
MARRIED_SET.add(changedPerson)
else:
MARRIED_SET.discard(changedPerson)
class Person(object):
...
#property
def married(self):
"""The person is married"""
return self._married
#married.setter
def married(self, newStatus):
self._married = newStatus
updateMarriedSet(self)
#married.deleter
def married(self):
del self._married
updateMarriedSet(self)
I can imagine this might, possibly, be useful to ensure accesses to getMarriedPeople() runs in O(1) time rather than amortized O(1) time.
The simple way is to generate the list on the fly e.g., as shown in #sr2222's answer.
As an alternative you could call an arbitrary callback each time MAR_STATUS changes. Use __new__ if Person instances are immutable or make MAR_STATUS a property and call registered callbacks in the setter method (see notifications in traits library for a more complex implementation).

Python: must __init__(self, foo) always be followed by self.foo = foo?

I've been striving mightily for three days to wrap my head around __init__ and "self", starting at Learn Python the Hard Way exercise 42, and moving on to read parts of the Python documentation, Alan Gauld's chapter on Object-Oriented Programming, Stack threads like this one on "self", and this one, and frankly, I'm getting ready to hit myself in the face with a brick until I pass out.
That being said, I've noticed a really common convention in initial __init__ definitions, which is to follow up with (self, foo) and then immediately declare, within that definition, that self.foo = foo.
From LPTHW, ex42:
class Game(object):
def __init__(self, start):
self.quips = ["a list", "of phrases", "here"]
self.start = start
From Alan Gauld:
def __init__(self,val): self.val = val
I'm in that horrible space where I can see that there's just One Big Thing I'm not getting, and I it's remaining opaque no matter how much I read about it and try to figure it out. Maybe if somebody can explain this little bit of consistency to me, the light will turn on. Is this because we need to say that "foo," the variable, will always be equal to the (foo) parameter, which is itself contained in the "self" parameter that's automatically assigned to the def it's attached to?
You might want to study up on object-oriented programming.
Loosely speaking, when you say
class Game(object):
def __init__(self, start):
self.start = start
you're saying:
I have a type of "thing" named Game
Whenever a new Game is created, it will demand me for some extra piece of information, start. (This is because the Game's initializer, named __init__, asks for this information.)
The initializer (also referred to as the "constructor", although that's a slight misnomer) needs to know which object (which was created just a moment ago) it's initializing. That's the first parameter -- which is usually called self by convention (but which you could call anything else...).
The game probably needs to remember what the start I gave it was. So it stores this information "inside" itself, by creating an instance variable also named start (nothing special, it's just whatever name you want), and assigning the value of the start parameter to the start variable.
If it doesn't store the value of the parameter, it won't have that informatoin available for later use.
Hope this explains what's happening.
I'm not quite sure what you're missing, so let me hit some basic items.
There are two "special" intialization names in a Python class object, one that is relatively rare for users to worry about, called __new__, and one that is much more usual, called __init__.
When you invoke a class-object constructor, e.g. (based on your example) x = Game(args), this first calls Game.__new__ to obtain memory in which to hold the object, and then Game.__init__ to fill in that memory. Most of the time, you can allow the underlying object.__new__ to allocate the memory, and you just need to fill it in. (You can use your own allocator for special weird rare cases like objects that never change and may share identities, the way ordinary integers do for instance. It's also for "metaclasses" that do weird stuff. But that's all a topic for much later.)
Your Game.__init__ function is called with "all the arguments to the constructor" plus one stashed in the front, which is the memory allocated for that object itself. (For "ordinary" objects that's mostly a dictionary of "attributes", plus the magic glue for classes, but for objects with __slots__ the attributes dictionary is omitted.) Naming that first argument self is just a convention—but don't violate it, people will hate you if you do. :-)
There's nothing that requires you to save all the arguments to the constructor. You can set any or all instance attributes you like:
class Weird(object):
def __init__(self, required_arg1, required_arg2, optional_arg3 = 'spam'):
self.irrelevant = False
def __str__(self):
...
The thing is that a Weird() instance is pretty useless after initialization, because you're required to pass two arguments that are simply thrown away, and given a third optional argument that is also thrown away:
x = Weird(42, 0.0, 'maybe')
The only point in requiring those thrown-away arguments is for future expansion, as it were (you might have these unused fields during early development). So if you're not immediately using and/or saving arguments to __init__, something is definitely weird in Weird.
Incidentally, the only reason for using (object) in the class definition is to indicate to Python 2.x that this is a "new-style" class (as distinguished from very-old-Python "instance only" classes). But it's generally best to use it—it makes what I said above about object.__new__ true, for instance :-) —until Python 3, where the old-style stuff is gone entirely.
Parameter names should be meaningful, to convey the role they play in the function/method or some information about their content.
You can see parameters of constructors to be even more important because they are often required for the working of the new instance and contain information which is needed in other methods of the class as well.
Imagine you have a Game class which accepts a playerList.
class Game:
def __init__(self, playerList):
self.playerList = playerList # or self.players = playerList
def printPlayerList(self):
print self.playerList # or print self.players
This list is needed in various methods of the class. Hence it makes sense to assign it to self.playerList. You could also assign it to self.players, whatever you feel more comfortable with and you think is understandable. But if you don't assign it to self.<somename> it won't be accessible in other methods.
So there is nothing special about how to name parameters/attributes/etc (there are some special class methods though), but using meaningful names makes the code easier to understand. Or would you understand the meaning of the above class if you had:
class G:
def __init__(self, x):
self.y = x
def ppl(self):
print self.y
? :) It does exactly the same but is harder to understand...

Categories

Resources