学习Python中的Dunder方法/属性,并谈谈 __version__.

881 阅读2分钟
import my_package
print(my_package.__version__)
# 1.2.3

Python __version__属性

Python 包含许多 "神奇的方法/属性"。其中一个是 __version__通常被称为 "Dunder版本",因为版本前后有双下划线。在这篇文章中,我将简要地看一下什么是Dunder方法/属性,并谈谈 __version__.

杜德方法/属性是做什么的?

Dunder方法/属性,也被称为 "魔法方法",执行两个基本功能。它们可以向解释器传递信息**(方法**),或者向程序员传递信息**(属性**)。

Dunders用于创建([__init__](https://blog.finxter.com/python-init/))、比较 ([__eq__](https://blog.finxter.com/python-__eq__-magic-method/))、属性访问(__version__),以及更多。有些是由程序员调用的,但有些像 [__add__](https://blog.finxter.com/python-__add__/)和其他运算符是 Python 内置的。

使用 [dir()](https://blog.finxter.com/python-dir-a-simple-guide-with-video/)函数和对象名称,你可以查看一个特定包中内置的所有方法和属性的列表。

class StarWars:
    __version__ = "19.7.7"

    def __init__(self, name, robot, affiliation):
        self.name = name
        self.robot = robot
        self.affiliation = affiliation

    def bio(self):
        print("{} and {} fight for the {}.".format(self.name, self.robot,      self.affiliation))


legends = StarWars("Luke Skywalker", "R2D2", "Rebel Force")
print(dir(StarWars))

输出

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'affiliation', 'name', 'robot']

Python __version__ 属性

这就把我们带到了__version__ "魔法属性"。Dunder版本是用来确定正在使用的包的版本。

在上面的代码中,我们可以添加一个打印语句来找出正在使用的类StarWars 的版本。

print(StarWars.__version__)

输出

19.7.7

你可以用这种格式来找出大多数包的版本。

import pandas
print(pandas.__version__)

输出结果

1.4.3

嵌入__version__

到此为止,我们所使用的例子都是比较基本的。

如果你正在构建一个可能依赖于外部软件包的应用程序,那么对软件包版本的调用可能会被嵌入到你的代码中。确保正确的版本被导入是很重要的。

这可以在构建时或运行时完成。我认为在运行前确定要使用的版本是比较安全的。创建一个version.py 文件。这个文件不包含其他代码,也不导入任何东西。它只包含版本属性(__version__ = "1.1.2")。让setup.py 文件读取它。

这有几个原因是有益的。首先,它限制了在版本改变时需要编辑的地方的数量。其次,你可以把version.py 文件导入到setup.py ,你不会因为把它存储在__init__.py 文件中而加载依赖性。

这里有一个例子。

# store version inside sample/_version.py file
__version__ = "1.1.2"

# inside sample/__init__.py:
from.version import__version__

# inside setup.py:
exec(open('sample/version.py').read())
setup(
    ...
    version=__version__,)

我在上一节提到,__version__ 将确定大多数软件包的版本。一些第三方软件包并不包含版本属性。因此,必须考虑到这种可能性,否则你的应用程序将在运行时失败。

例子

raise RuntimeError("Unable to find version string")