Is possible and, if so, common practice to initialize an object inside a class in Python?
self.field = Class()
object-orientedpython
Is possible and, if so, common practice to initialize an object inside a class in Python?
self.field = Class()
Your friend was wrong. Methods are attributes.
Everything in Python is objects, really, with methods and functions and anything with a __call__()
method being callable objects. They are all objects that respond to the ()
call expression syntax.
Attributes then, are objects found by attribute lookup on other objects. It doesn't matter to the attribute lookup mechanism that what is being looked up is a callable object or not.
You can observe this behaviour by looking up just the method, and not calling it:
>>> class Foo(object):
... def bar(self):
... pass
...
>>> f = Foo()
>>> f.bar
<bound method Foo.bar of <__main__.Foo object at 0x1023f5590>>
Here f.bar
is an attribute lookup expression, the result is a method object.
Of course, your friend me be a little bit right too; what is really happening is that methods are special objects that wrap functions, keeping references to the underlying instance and original function, and are created on the fly by accessing the function as an attribute. But that may be complicating matters a little when you first start out trying to understand Python objects. If you are interested in how all that works, read the Python Descriptor HOWTO to see how attributes with special methods are treated differently on certain types of attribute access.
This all works because Python is a dynamic language; no type declarations are required. As far as the language is concerned, it doesn't matter if Foo.bar
is a string, a dictionary, a generator, or a method. This is in contrast to compiled languages, where data is very separate from methods, and each field on an instance needs to be pinned down to a specific type beforehand. Methods generally are not objects, thus a separate concept from data.
In the below example of a Town class, the behavior of moving to/from a town is split up among the Town class and Inhabitant class. The code works. But I am wondering if there are compelling reasons to assign this behavior to only one class, e.g. allow the Town method
addpeople
to update the Inhabitant attribute town so it's possible to track each inhabitant's place of residence.
There is actually a good reason to not assign this behavior to only one class and keep it similar to what you have - in object-oriented programming you really want to have each object maintain control over its own data. Your code can easily become very complicated and hard to debug if you change variables outside of the object that the variable belongs to. This is part of the concept of encapsulation that is central to object-oriented programming.
Another part of OOP that is relevant here is abstraction, i.e you want the interaction between objects in your code to make sense at a higher level. Just from looking at this sample code, I would guess that the inhabitants of the towns are more the focus of your program than the towns themselves. If the user is interacting more with the town, I would expect the town to be doing more of the work (Town.addpeople
calling Inhabitant.move
, for example).
So as you are writing your program, think about which entities will be the ones doing the work. When your code matches your intuitive abstraction of what is happening, it will be much easier for you to keep track of what is going on and not introduce bugs into your code.
One other piece of advice I would give you may or may not be helpful, depending on what this project is for. If this is a program you are going to be actually using, maintaining, and upgrading, write a throwaway prototype first. As Joel Cornett mentioned in the comment, "It depends on the use case", meaning that in order to know the best way to write the code you have to understand the situation. Some of this comes from experience, but unless you are perpetually writing pretty much the same program time and again, you will run into a situation that is not entirely familiar. Writing a prototype is an excellent way to get some experience with the specific problem that you are facing, because you often will not be able to see why one way or another will work better until you are fairly far into writing the program.
One thing that prevents people from creating a good system is that they get attached to their code. So if you choose to write a prototype, realize that it is a throwaway - something you write rapidly just for the purpose of getting a good feel for the problem. It can also help if you realize while you're writing it that it doesn't even have to work, as long as it helps you figure out what it would take for it to work well. Once you've written your prototype, you will have a much better feel for how you should have written your code. Then you can start over and write it correctly much faster.
In short, "It depends on the use case", so make sure you understand the use case and have the code match your understanding.
Best Answer
Everything in Python is an object, so yes, this is common practice. You could not create a meaningful Python program without creating other instances in your own classes.