Classes - "delegation" question.

Ivan Evstegneev webmailgroups at gmail.com
Wed Dec 17 09:35:36 EST 2014


Hello guys,

I have a question about "delegation" coding pattern(I'm working with Python
3.4).
In order to describe my question , I'll provide particular example:

Let assume I have two classes written in module named person.py:


Case 1:

class Person:
	def __init__(self, name, job = None, pay =0):
		self.name = name
		self.job = job
		self.pay = pay
	def lastName(self):
		return self.name.split()[-1]
	def giveRaise(self, percent):
		self.pay = int(sel.pay * (1 + percent))
	def __repr__(self):
		return '[Person: %s, %s]' % (self.name, self.pay)

class Manager(Person):
	def giveRaise(self, percent, bonus = .10):
		Person.giveRaise(self, percent + bonus)


Case 2: 


class Person: 
	....the same...

class Manager: 
	def __init__(self, name, pay):
		self.person = Person(name, 'mgr', pay)
	def giveRaise(self, percent, bonus = .10):
		self.person.giveRaise(percent + bonus)
	def __getattr__(self, attr):
		return getattr(self.person, attr)
	def __repr__(self):
		return str(self.person) 

 
I also used some test code proposed by the book:

if __name__ == '__main__':
	bob = Person('Bob Smith')
	sue = Person('Sue Jones', job='dev', pay=100000)
	print(bob)
	print(sue)
	print(bob.lastName(), sue.lastName())
	sue.giveRaise(.10)
	print(sue)
	tom = Manager('Tom Jones', 50000) # Job name not needed:
	tom.giveRaise(.10)

	print(tom.lastName())
	print(tom)


As I can understand from the above code : 

When code looks like in  Case 1, it actually works with standard
"inheritance" model. (with sub and super-class definitions).
Also according to the book:
***************************************************************
This code leverages the fact that a class's method can always be called
either through
an instance (the usual way, where Python sends the instance to the self
argument
automatically) or through the class (the less common scheme, where you must
pass the
instance manually). In more symbolic terms, recall that a normal method call
of this
form:
	instance.method(args...)
is automatically translated by Python into this equivalent form:
	class.method(instance, args...)
 ***************************************************************

Furthermore:

***************************************************************
Python provides it automatically only for calls made through an instance.
For calls 
through the class name, you need to send an instance to self yourself; for
code inside 
a method like giveRaise, self already is the subject of the call, and hence
the instance 
to pass along.
Calling through the class directly effectively subverts inheritance and
kicks the call
higher up the class tree to run a specific version.
****************************************************************

What is considered as a "call" in this context?

Is it a code inside class method?

For instance(relates to the "Case 1"):

def giveRaise(self, percent, bonus = .10):
		Person.giveRaise(self, percent + bonus)

The "call" will be : Person.giveRaise(self, percent + bonus)   ?

In such a case, when I create an instance:

>>> tom = Manager('Tom Jones', 50000)

and then invoke giveRaise method 

>>> tom.giveRaise(.10)

I essentially say this:

"class.method(instance, args...) "

Where class is "Person" and method is "giveRaise" and instance is "tom"?

Moreover, because of how it defined (a method giveRaise), I make a "call"
through the class name?

What is the "call" through instance? 

Is it this one(according to Case 1):

class Person:
	.......
	def giveRaise(self, percent):
		self.pay = int(sel.pay * (1 + percent))
	.......

and then:

>>> bob = Person('Bob Smith', 'dev', 30000)
>>> bob.giveRaise(.10)     <   ---- Is this call through instance? 



Questions regard to "Case 2" example:

class Person: 
	....the same...

class Manager: 
	def __init__(self, name, pay):
		self.person = Person(name, 'mgr', pay)   <-------
Initialization of Manager's attribute named  'self.person" and embedding  a
Person object. 
	
	def giveRaise(self, percent, bonus = .10):                < ------
Defenition of Manager's method named "giveRaise" and according to the book:
		self.person.giveRaise(percent + bonus)	 "Intercept and
delegate"
	..............

My question here is substantially the same:

On the one hand we embedding "Person" into "Manager" class, 

On the other hand, when I write this code:

>>> tom = Manager('Tom Jones', 5000)

I create an instance of Manager that have an attribute named: tom.person,
which in turn is a class named Person.

And when typing:

>>>tom.giveRaise(.10)

I do kinda same thing. 
For my assumption I say:

Person.giveRaise( percent + bonus)         (when self.person actually
implies "Person")

But why we don't use "self" argument in --> self.person.giveRaise(percent +
bonus)?
So it should look like --> self.person.giveRaise(self, percent + bonus)?

Is it because of embedding  "Person" into "Manager" so there is no hierarchy
considerations, 
and by embedding(compositing) classes, we place them at the same level? 
And as it seems to me, there is no relevance for " inheritance" stuff.

As a direct consequence, when I type:

>>> tom.giveRaise(.10)

I made a "call" through instance, and there is no need for "self"?  

Thanks a lot in advance,

Ivan  







 



 










More information about the Python-list mailing list