Python: must __init __ (self, foo) always follows self.foo = foo?

For a very long time, I tried for three days to wrap my head around __init__ and "self", starting with the Learn Python Hard Way 42 exercise and going on to read parts of the Python documentation, Alan Gauld's chapter on object-oriented programming , Draw threads like this on " myself, " and this one , and to be honest, I'm going to hit myself with a brick until I leave.

At the same time, I noticed a really general convention in the initial __init__ definitions, which should track (self, foo), and then immediately declare self.foo = foo in this definition.

From LPTHW, ex42:

 class Game(object): def __init__(self, start): self.quips = ["a list", "of phrases", "here"] self.start = start 

From Alan Galld:

 def __init__(self,val): self.val = val 

I am in such a terrible place where I see that there is just one big thing that I don’t get, and I remain opaque, no matter how much I read about it and try to understand it. Maybe if someone can explain a little coherence to me, the light will turn on. Is it because we need to say that "foo", a variable, will always be equal to the parameter (foo), which itself is contained in the parameter "self", which is automatically assigned to the definition to which it is bound?

+4
source share
3 answers

You might want to learn about object-oriented programming.

In short, when you say

 class Game(object): def __init__(self, start): self.start = start 

you speak:

  • I have a type of "thing" called Game

  • Whenever a new Game is created, it will require additional information from me, start . (This is because the Game initializer, called __init__ , requests this information.)

  • The initializer (also called the "constructor", although it contains a slight misunderstanding) must know which object (which was created just a moment ago) it initializes. This is the first parameter that is usually called self by convention (but which you could call something else ...).

  • The game should probably remember that I gave it a start . Thus, it stores this information “inside” on its own, creating an instance variable with the name start (nothing special, it's just any name you want) and assigning the value of the start parameter to the start variable.

    • If he does not save the value of the parameter, he will not have available information for later use.

Hope this explains what happens.

+6
source

I'm not quite sure what you are missing, so let me put on some basic elements.

There are two “special” names for intialization in the Python class object, which are relatively rare for users, called __new__ , and a more common one, called __init__ .

When calling the constructor of the object class, for example. (based on your example) x = Game(args) , this first calls Game.__new__ to get memory to hold the object, and then Game.__init__ to fill that memory. In most cases, you can let the underlying object.__new__ allocate memory, and you just need to fill it up. (You can use your own dispenser for special strange rare cases, such as objects that never change and can share identifiers, for example, ordinary "ordinary" integers, as well as for "metaclasses" that do strange things, but all this topic much later.)

Your Game.__init__ is called with "all constructor arguments" plus one hidden in front, which is the memory allocated for this object. (For "ordinary" objects, which are mainly a dictionary of "attributes", plus magic glue for classes, but for objects with __slots__ attribute dictionary is omitted.) The naming of this first argument self is just a convention, but don Violate this, people will hate it you if you do this. :-)

There is nothing that requires you to save all the constructor arguments. You can set any or all instance attributes that you like:

 class Weird(object): def __init__(self, required_arg1, required_arg2, optional_arg3 = 'spam'): self.irrelevant = False def __str__(self): ... 

The fact is that after initialization, the Weird () instance is pretty useless, because you need to pass two arguments that are just thrown away and give a third optional argument, which is also discarded:

 x = Weird(42, 0.0, 'maybe') 

The only point requiring dropped arguments is to expand further (you might have these unused fields during early development). Therefore, if you do not immediately use and / or store the arguments in __init__ , something is definitely strange in Weird .

By the way, the only reason to use (object) in a class definition is to tell Python 2.x that it is a "new style" class (as opposed to the "only for very old Python instances" classes), but it’s best to use it - it does that that I said above object.__new__ true, for example :-) -until Python 3, where old-style things completely disappeared.

+2
source

Parameter names must be meaningful in order to convey the role they play in the function / method, or some information about their content.

You can see that the parameters of the constructors are even more important, since they are often necessary for the operation of a new instance and contain information that is necessary in other methods of the class.

Imagine you have a Game class that accepts 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 class methods. Therefore, it makes sense to assign it self.playerList . You can also assign it to self.players , so that you feel more comfortable, and you consider it understandable. But if you have not assigned it self.<somename> , it will not be available in another way.

So there is nothing special about calling parameters / attributes / etc ( there are some special class methods, though ), but using meaningful names makes the code more understandable. Or would you understand the meaning of this class if you had:

 class G: def __init__(self, x): self.y = x def ppl(self): print self.y 

? :) He does the same, but harder to understand ...

0
source

Source: https://habr.com/ru/post/1401716/


All Articles