V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
codists
V2EX  ›  Python

翻译:《实用的 Python 编程》03_06_Design_discussion

  •  
  •   codists ·
    codists · 2021-03-05 22:26:46 +08:00 · 1468 次点击
    这是一个创建于 1365 天前的主题,其中的信息可能已经有所发展或是发生改变。

    3.6 设计讨论

    本节,我们重新考虑之前所做的设计决策。

    文件名与可迭代对象

    考虑以下两个返回相同输出的程序。

    # Provide a filename
    def read_data(filename):
        records = []
        with open(filename) as f:
            for line in f:
                ...
                records.append(r)
        return records
    
    d = read_data('file.csv')
    
    # Provide lines
    def read_data(lines):
        records = []
        for line in lines:
            ...
            records.append(r)
        return records
    
    with open('file.csv') as f:
        d = read_data(f)
    
    • 你更倾向于使用哪个函数?为什么?
    • 哪个函数更灵活?

    鸭子类型( Duck Typing )

    在计算机程序设计中,"鸭子类型"用于确定一个对象是否可用于特定目的。这是"鸭子测试"的一种应用。

    如果它看起来像鸭子、游泳像鸭子、叫声像鸭子,那么它可能就是只鸭子。

    上述第二个 read_data() 函数接受任何可迭代对象,而不仅是文件行。

    def read_data(lines):
        records = []
        for line in lines:
            ...
            records.append(r)
        return records
    

    这意味这我们可以使用它处理其它的行( lines )

    # A CSV file
    lines = open('data.csv')
    data = read_data(lines)
    
    # A zipped file
    lines = gzip.open('data.csv.gz','rt')
    data = read_data(lines)
    
    # The Standard Input
    lines = sys.stdin
    data = read_data(lines)
    
    # A list of strings
    lines = ['ACME,50,91.1','IBM,75,123.45', ... ]
    data = read_data(lines)
    

    这种设计具有很大的灵活性。

    问题:我们应该拥抱还是反对这种灵活性?

    库设计最佳实践

    通常,拥抱灵活性可以更好的服务于代码库。不要限制你的选择,灵活性大,带来的威力也大。

    练习

    练习 3.17:从文件名到类文件对象

    现在,你已经创建了一个包含 parse_csv() 函数的 fileparse.py 文件。parse_csv() 函数像下面这样工作:

    >>> import fileparse
    >>> portfolio = fileparse.parse_csv('Data/portfolio.csv', types=[str,int,float])
    >>>
    

    虽然函数接受的是一个文件名,但是,你可以使代码更具灵活性。请求修改函数,以便它可以接受任何类文件或者可迭代对象。例如:

    >>> import fileparse
    >>> import gzip
    >>> with gzip.open('Data/portfolio.csv.gz', 'rt') as file:
    ...      port = fileparse.parse_csv(file, types=[str,int,float])
    ...
    >>> lines = ['name,shares,price', 'AA,100,34.23', 'IBM,50,91.1', 'HPE,75,45.1']
    >>> port = fileparse.parse_csv(lines, types=[str,int,float])
    >>>
    

    在新的代码中,如果像以前一样传递一个文件名会发生什么?

    >>> port = fileparse.parse_csv('Data/portfolio.csv', types=[str,int,float])
    >>> port
    ... look at output (it should be crazy) ...
    >>>
    

    正如上面代码显示的那样,这可能带来意想不到的结果,所以,修改的时候需要小心一些。你可以添加安全检查来避免这种情况吗?

    练习 3.18:修复( fix )现有函数

    请修复 report.py 文件中的 read_portfolio()read_prices() 函数。以便它们可以使用修改后的 parse_csv() 函数。这应该只涉及较小的修改。之后,report.pypcost.py 程序应能够像以往一样工作。

    注:完整翻译见 https://github.com/codists/practical-python-zh

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2879 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 08:54 · PVG 16:54 · LAX 00:54 · JFK 03:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.