static method and passing var?

in “byte of python” book there is an example of using static var as a decorator

the example of the robot class on page 84

class Robot:
‘’‘Represents a robot, with a name.’’’
population = 0 # A class variable, counting the number of robots


then at the end the static function

def howMany():
‘’‘Prints the current population.’’’
print(‘We have {0:d} robots.’.format(Robot.population))
howMany = staticmethod(howMany)

which prints something like

Initializing R2-D2

Greetings, my masters call me R2-D2

We have 1 robots

but how does the population of robot is passed to the howmany method ?

i don’t see any vars being pass here ?

can someone explain this and how it is done?
what happen if there is more then one class vars ?

Thanks

If I look at an older version of book, this example is at page 71, there is no Robots but just Persons, but anyways…

…There they increase the class variable named population every init() call. init() call gets called every time implicitly when you create an instance of your object class:

r=Robot(“SnifiX”) # calls behind scenes implicitly the Robot.init()

which calls

Robot.population+=1

The number of robot population gets decreased every time you delete an object of class Robot. When you delete an object (it happens for example when writing del r), the class again implicitly calls the Robot.del() method, where the decrease of Robot.population happens:

Robot.population-=1

The howMany() method reads the class variable named population. It reads it via the name Robot.population, because it is class variable, and we are inside of the scope of defining function with def howMany(). At outer scope (that is: the class scope) it is just called population but in inner scope it needs to be called as Robot.population, but they both point to same variable.

The call to howMany = staticmethod(howMany) is to change the scope of function definion. It does not affect the Robot.population variable. If you don’t change the scope of this howMany function (Notice it is a function, not variable!) you can only call it via class instances (that is with actual objects):

r.howMany() # prints the population

but

Robot.howMany() # doesn’t work, but works only after staticmethod

The parenthesis () operation howMany() is the call to the function, but the variable without parenthesis howMany is a formal way to handle the function as it were like an normal variable. (…like it is in Python, remember the famous rule: “Everything in Python is an object.”)

ok but what indicate to this howmany methods to take the robot population variable?

i can see one class var for robot population but if there was more then one class vars
then what would happen?

the problem i have is that
in another words there is no indication to how howmany read this var and why this var only!

if i have to i’l copy the new robot class here from book to show all methods et…
might be easier to visualize it !

Thanks

import random
random.seed(0)

class Robot:
  population=0 # class variable
  footsteps=0 # class variable
  def __init__(self):
    population=45 # meaningless local variable
    self.population=random.randint(0,100) # r1.pop, r2.pop etc...
    Robot.population+=1 # class variable
    print(population, self.population, Robot.population)


print(Robot.population) # prints 0
r1=Robot() # prints 45 85 1
r2=Robot() # prints 45 76 2
r3=Robot() # prints 45 42 3

print(Robot.population) # prints 3
print(r1.population) # prints 85
print(Robot.footsteps) # prints 0
print(population) # ERROR! There is no such global variable

If you look this code, and go step by step why each line print what they print, does it functiate like you’d expect, or does it answer anyway the question?

sorry but stil dont see how it gets the value !

i understand each single line

from class variable or local variable

it is all very logical each var is a taking a specific value

no problems with that!

but in the case of the robot population and static method

i still don’t get how the howmany function is getting the value from robot .population

here is the code


 
import bpy
 
 
class Robot:
    '''Represents a robot, with a name.'''
 
    # A class variable, counting the number of robots
    population = 0
 
    def __init__(self, name):
        '''Initializes the data.'''
        self.name = name
        print('(Initializing {0})'.format(self.name))
 
        # When this person is created, the robot
        # adds to the population
        Robot.population += 1
 
    def __del__(self):
        '''I am dying.'''
        print('{0} is being destroyed!'.format(self.name))
 
        Robot.population -= 1
 
        if Robot.population == 0:
            print('{0} was the last one.'.format(self.name))
        else:
            print('There are still {0:d} robots working.'.format(Robot.population))
 
    def sayHi(self):
        '''Greeting by the robot.
 
       ''' Yeah, they can do that.'''
 
        print('Greetings, my masters call me {0}.'.format(self.name))
 
    def howMany():
        '''Prints the current population.'''
        print('We have {0:d} robots.'.format(Robot.population))
    howMany = staticmethod(howMany)
 
droid1 = Robot('R2-D2')
droid1.sayHi()
Robot.howMany()
 
 

########

where does Robot.howMany() get the value and how !

i can see the print line
print(‘We have {0:d} robots.’.format(Robot.population))
is taking the Robot.population value but how does howmany function gets it ?

is it passed on and how

this “howmany” name is not a predefine function in python it could be anyname here
so it has to be given a value or calculalte it but how ?

i guess it’s getting i from this line

howMany = staticmethod(howMany)

but how does the staticmethod(howMany) get it ?

also in the book there is another way to define this

which are call decorator as per the book

@staticmethod
def howMany():
‘’‘Prints the current population.’’’
print(‘We have {0:d} robots.’.format(Robot.population))

but it does not explain the logic here

how does the robot.population is given it’s value to the function ?

theses decorator can do very strange things like shown in the link gien in book

but i’ll talk about theses later

http://www.ibm.com/developerworks/linux/library/l-cpdecor.html

Thanks

hre is another example with decorator
which is a littel bit more complicated to follow

but again here it looks like there is almost a magic way to pass the info to the function


 >>> def addspam(fn):
...     def new(*args):
...         print "spam, spam, spam"
...         return fn(*args)
...     return new
...
>>> @addspam
... def useful(a, b):
...     print a**2 + b**2
...
>>> useful(3,4)
spam, spam, spam
25
 
 

here it lool like it’s taking the value from the print line ?

so where is the logic here ?
cause there is nothing written saying to transfert the value in the print line to the function!

so does it measn that you cannot ahve anything else in this function
or it wont work !

like having other print statement or command to do some math ?

another thing here is that usefull def seems to replace the first def name addspam because of the decorator!

Thanks

@Ricky, you are still mixing things together and wonder why you dont understand.
Look again at Snifix very good example, if you cannot understand it, go back and read some tutorials about “variable scope range”, maybe you get a clue whats your problem.

The scope range of a variable … inside a function is different from other not-inside-this-function variables. You know about “global” and the examples from Snifix variable-usage?

Last, if you never used an object-oriented language before, this point is hard to understand. You may skip it first and try to understand the features, which are not object-oriented. Speaking with my own history in mind, i would suggest to learn C and later C++ and not the way to learn C++ at once from the object-side, trying to skip the “bascis”. Believe me or not, it is always possible to program all this object-oriented-stuff with simple not-object-capable structures. And dont use complicated object-creations if you only need a few “global variables”. In python declare those variables and if needed in a function, then use them as read-only or if you need them to be writable, then declare those vars inside the function as “global”. If you need a lot of those vars for your program-function-communication, then you quickly will run into problems mangling the names and using the wrong variable-name inside a function. Thats the point the classes come in handy, because they create automatically a sparate name-space for those vars and you dont need it to do it manually.

It is exactly here, the underlined variable:


print('We have {0:d} robots.'.format(<i>Robot.population</i>))

When you declare your class Robot the first time, all the class variables get initialized and have a global status from then on.

Same as if you call

print(a) # ERROR!

you’ll get an error because a is not declared. But if you declare it, all goes ok:

a=5
print(a) # prints 5

If I try the same with classes:

First you try to call

print(Robot.population) # ERROR!

But if you declare it the same way we declared a earlier, it goes ok

class Robot:
  population=0
print(Robot.population) # prints 0

It may be unclear to you the way Python handles with code: When you declare a class, it is not just a declaration of class, it is executing the class. Executing means Python creates the class with corresponding variables inside it and give a visibility status for them. Executing happens always in the same order the code lines in your code are written. In this case, there will be a global object named Robot. This global object has attributes like Robot.population and methods like Robot.howMany(). “Creating” means the class is from then on a structure in memory. All the class variables are found there, and they get there just because Python not just declares a class, but executes it.

i already know about global and have a good idea o scope variable range
even if i’m not a programmer
i did many little script in python including some class
but right now i;m trying to understand this new concept of decorator
which is not really explain well in the dive into python book

now i played with the second example

and modified it a little


 	
def addspam(fn):
	def new(*args):
			print ("spam, spam, spam")			#  Any number of print inside here 
			print ("salut coco")
			print ("Ricky")
			X=5
			y=7
			return fn(*args)
	return new
												#	Defines a decorator for addspam
@addspam
def useful(a, b,c):
	print ( a**2 + b**2)
	print ( a**3 + b**3)
	c=( a**4 + b**4)
	
########################
	
useful(3,4,5)										# This print /  spam spam spamm  and then 25

this prints he following

spam, spam, spam
salut coco
Ricky
25
91

##################

it looks like it’s taking only what’s inside the print statement
anything other like math statements is ignored and not influencing the results

so it looks like the value for the function comes from the each print statement inside de definition or decorator !

am i on the right path here ?

Thanks

Good discussion. I’m a python noob myself, and I wonder at the necessity of having decorators and such. It seems like ninja-level programming that just confuses new folks. But it seems to me here that the useful() acquires shorthand inheritance from @addspam. Would it be clearer to define a class Addspam, and then declare class useful(Addspam) ?? Wouldn’t that achieve the same thing?

see the thread for a discusion between old style class and decorator

it can be done with class only but it’s easier written with decorator

but i’m still wondering how it works but also is it really usefull at all

i mean on all the scripts in 2.5 done up to now i;v seen this may be ounce

so i think you can easily live whitout theses

but it is one thing that i saw in python book and wanted to understand how theses works
and if really usefull in writting scripts in 2.5 !

salutations