Python Distilled by David M. Beazley

Python Distilled by David M. Beazley

Author:David M. Beazley [David M. Beazley]
Language: eng
Format: epub
Publisher: Addison-Wesley Professional
Published: 2021-09-16T16:00:00+00:00


7.13 Static Methods

Sometimes a class is merely used as a namespace for functions declared as static methods using @staticmethod. Unlike a normal method or class method, a static method does not take an extra self or cls argument. A static method is just a ordinary function that happens to be defined inside a class. For example:

Click here to view code image

class Ops: @staticmethod def add(x, y): return x + y @staticmethod def sub(x, y): return x - y

You don’t normally create instances of such a class. Instead, call the functions directly through the class:

Click here to view code image

a = Ops.add(2, 3) # a = 5 b = Ops.sub(4, 5) # a = -1

Sometimes other classes will use a collection of static methods like this to implement “swappable” or “configurable” behavior, or as something that loosely mimics the behavior of an import module. Consider the use of inheritance in the earlier Account example:

Click here to view code image

class Account: def __init__(self, owner, balance): self.owner = owner self.balance = balance def __repr__(self): return f'{type(self).__name__}({self.owner!r}, {self.balance!r})' def deposit(self, amount): self.balance += amount def withdraw(self, amount): self.balance -= amount def inquiry(self): return self.balance # A special "Evil" account class EvilAccount(Account): def deposit(self, amount): self.balance += 0.95 * amount def inquiry(self): if random.randint(0,4) == 1: return 1.10 * self.balance else: return self.balance

The use of inheritance here is a little strange. It introduces two different kinds of objects, Account and EvilAccount. There is also no obvious way to change an existing Account instance into an EvilAccount or back, because this involves changing the instance type. Perhaps it’s better to have evil manifest as a kind of an account policy instead. Here is an alternate formulation of Account that does that with static methods:

Click here to view code image

class StandardPolicy: @staticmethod def deposit(account, amount): account.balance += amount @staticmethod def withdraw(account, amount): account.balance -= amount @staticmethod def inquiry(account): return account.balance class EvilPolicy(StandardPolicy): @staticmethod def deposit(account, amount): account.balance += 0.95*amount @staticmethod def inquiry(account): if random.randint(0,4) == 1: return 1.10 * account.balance else: return account.balance class Account: def __init__(self, owner, balance, *, policy=StandardPolicy): self.owner = owner self.balance = balance self.policy = policy def __repr__(self): return f'Account({self.policy}, {self.owner!r}, {self.balance!r})' def deposit(self, amount): self.policy.deposit(self, amount) def withdraw(self, amount): self.policy.withdraw(self, amount) def inquiry(self): return self.policy.inquiry(self)

In this reformulation, there is only one type of instance that gets created, Account. However, it has a special policy attribute that provides the implementation of various methods. If needed, the policy can be dynamically changed on an existing Account instance:

Click here to view code image

>>> a = Account('Guido', 1000.0) >>> a.policy <class 'StandardPolicy'> >>> a.deposit(500) >>> a.inquiry() 1500.0 >>> a.policy = EvilPolicy >>> a.deposit(500) >>> a.inquiry() # Could randomly be 1.10x more 1975.0 >>>

One reason why @staticmethod makes sense here is that there is no need to create instances of StandardPolicy or EvilPolicy. The main purpose of these classes is to organize a bundle of methods, not to store additional instance data that’s related to Account. Still, the loosely coupled nature of Python could certainly allow a policy to be upgraded to hold its own data.



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.