Python getters and setters
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Sat Aug 17 19:40:30 EDT 2013
On Sun, 18 Aug 2013 00:52:06 +0200, Irmen de Jong wrote:
> On 17-8-2013 19:18, Steven D'Aprano wrote:
[...]
>> How is this:
>>
>> obj.data_length()
>>
>> easier for the user than this?
>>
>> len(obj.data)
>>
>>
> It's not easier for the user perse, but it might be preferable from a
> design point of view. For the direct components of obj, it's probably
> alright to access them directly.
Yes, and my comments assume that obj.data is public in the first place.
> There's something called the Law of
> Demeter aka principle of least knowledge
> (http://en.wikipedia.org/wiki/Law_of_Demeter) though. It basically
> argues against the use of "more than one dot". Doing that ties the use
> of the object more to the actual implementation/internal structure of
> the object.
A very good point! But not an easy one to understand. The Law of Demeter
can be described as "if you want to walk the dog, talk to the dog, not
the dog's legs". Another classic example is of the paperboy who reaches
into your back pocket, pulls out your wallet, removes the money he is
owed, then puts your wallet back:
# No, this is bad design.
class Paperboy:
def take_payment(self, customer):
payment_owed = 2
wallet = customer.backpocket.get_wallet()
money = wallet.take(payment_owed)
self.money += money
customer.backpocket.put_wallet(wallet)
It's bad design because it ties the paperboy to one specific
implementation of customer. Perhaps the customer carries his wallet in a
front pocket. Or she carries her purse in her handbag. Or she is the
Queen of England, and doesn't carry money at all, but has a flunky who
carries money for her. Better is:
class Paperboy:
def take_payment(self, customer):
payment_owed = 2
self.money = customer.get_payment(payment_owed)
and raise an error if the customer doesn't implement get_payment.
The Law of Demeter is often characterised as "don't use more than one dot
at a time", but of course that's wrong for two reasons:
- Re-writing take_payment to avoid multiple dots is still wrong:
def take_payment(self, customer):
payment_owed = 2
pocket = customer.backpocket
wallet = pocket.get_wallet()
money = wallet.take(payment_owed)
self.money += money
pocket.put_wallet(wallet)
- If the attribute is part of the public interface, then it is okay to
use it no matter how deep (how many dots) it is.
The Law of Demeter is really about being careful about what interface
your classes provide. Customers should provide a get_payment method; dogs
should provide a walk method. You shouldn't have to send individual step
messages to the dog's legs.
--
Steven
More information about the Python-list
mailing list