Files
coding-mentor-agent/kb/python-course-kb-practical-python/wiki/exercises/7-7-using-closures-to-avoid-repetition.md
T

2.3 KiB

id, source_exercise_id, title, section, source_path, source_repo, source_commit, student_visible_solution, has_private_solution, skip
id source_exercise_id title section source_path source_repo source_commit student_visible_solution has_private_solution skip
practical-python-7.7 7.7 Using Closures to Avoid Repetition 7.3 Returning Functions 07_Advanced_Topics/03_Returning_functions.md https://github.com/dabeaz-course/practical-python 93dca856b41c61a0a0f85ae334116e4c125629ea false false false

Exercise 7.7: Using Closures to Avoid Repetition

Source: Practical Python Programming, 07_Advanced_Topics/03_Returning_functions.md.

Exercise 7.7: Using Closures to Avoid Repetition

One of the more powerful features of closures is their use in generating repetitive code. If you refer back to Exercise 5.7, recall the code for defining a property with type checking.

class Stock:
    def __init__(self, name, shares, price):
        self.name = name
        self.shares = shares
        self.price = price
    ...
    @property
    def shares(self):
        return self._shares

    @shares.setter
    def shares(self, value):
        if not isinstance(value, int):
            raise TypeError('Expected int')
        self._shares = value
    ...

Instead of repeatedly typing that code over and over again, you can automatically create it using a closure.

Make a file typedproperty.py and put the following code in it:

# typedproperty.py

def typedproperty(name, expected_type):
    private_name = '_' + name
    @property
    def prop(self):
        return getattr(self, private_name)

    @prop.setter
    def prop(self, value):
        if not isinstance(value, expected_type):
            raise TypeError(f'Expected {expected_type}')
        setattr(self, private_name, value)

    return prop

Now, try it out by defining a class like this:

from typedproperty import typedproperty

class Stock:
    name = typedproperty('name', str)
    shares = typedproperty('shares', int)
    price = typedproperty('price', float)

    def __init__(self, name, shares, price):
        self.name = name
        self.shares = shares
        self.price = price

Try creating an instance and verifying that type-checking works.

>>> s = Stock('IBM', 50, 91.1)
>>> s.name
'IBM'
>>> s.shares = '100'
... should get a TypeError ...
>>>

关联来源