实例变量Python的类型提示约定 [英] Type Hints Convention for Instance Variables Python

查看:174
本文介绍了实例变量Python的类型提示约定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不确定类型提示实例变量的Python约定-我一直在 __ init __ 构造函数自变量中进行操作,如下所示:

  class LoggedVar(Generic [T]):
def __init __(自身,值:T,名称:str,记录器:Logger)->无:
self.name =名称
self.logger =记录器
self.value =值`

链接到上述代码段: https://docs.python.org/3/library/typing.html#user-defined-generic-types



但我也看到了PEP惯例,例如这样注释实例变量(下面的代码段),然后也在 __ init __ 参数中进行类型提示:

  class BasicStarship:
船长:str ='Picard'#具有默认
损坏的实例变量:int#没有默认
的实例变量:ClassVar [ Dict [str,int]] = {}#类变量`

def __init __(self,伤害:int,队长:str = None):
self.damage =伤害
如果队长:
self.captain =队长#否则保留默认的

最后,在PEP526文章的后面,他们说为了方便和习惯起见,可以做以下事情:

  class Box(Generic [T]):
def __init __(self,content):
self.content:T =内容

上面两个代码段的网址:
https://www.python.org/dev/peps/pep-0526/ #class-and-instance-variable-annotations



因此,其中一项公约比我应该遵循的其他公约更好/更广泛地被接受(更好的可读性等。)?

解决方案

我建议使用第一个版本,在该版本中,将类型分配给<$ c在大多数情况下,$ c> __ init __ 方法的参数。



该特定方法的冗余最少,同时仍允许类型检查器验证你是 在代码的其他位置正确调用 __ init __ 方法。



我建议使用第二个或第三个版本,其中当您的 __ init __ 方法变得复杂到足以使您的字段(在 __ init __ 内部或外部)显式注释时,或以下情况中的更多者适用:


  1. 不再那么直白了,您的字段究竟以什么开头

  2. 参数与字段之间不再存在一对一的映射

  3. 您具有复杂的初始化逻辑,从而模糊了字段的分配方式。

但是,我不清楚是首选第二版还是第三版-我个人更喜欢第三版,因为从概念上讲它更干净,而且看上去混合了实例与类属性的概念,但我不能否认第二个版本看起来更干净。



我在'typing'的gitter频道上问了一下,得到了Guido的以下回复(谁不知道,他做了Python? ,目前正在研究mypy并输入相关内容):


似乎有强烈的意见。我确实确实更喜欢将属性注释放在类主体中,而不是在 __ init __ 和其他方法中散布它们。我还认为,使用PEP 526,这将是未来(也包括基于类的NamedTuple声明以及 https:/ /github.com/ericvsmith/dataclasses )。


引用链接



因此,似乎建议使用第二个版本第三,以这种方式定义的类将在将来的某个时刻更加深入地集成到Python语言本身中!



编辑: PEP 557,数据类最近被接受,并且似乎已经步入(?)Python 3.7版本。

Unsure of the Python convention for type hinting instance variables - I've been doing them within the __init__ constructor arguments like seen here:

class LoggedVar(Generic[T]):
    def __init__(self, value: T, name: str, logger: Logger) -> None:
        self.name = name
        self.logger = logger
        self.value = value`

link to above code snippet: https://docs.python.org/3/library/typing.html#user-defined-generic-types

But I also see the PEP conventions of annotating instance variables as such(snippet below) and then also doing type hinting within the __init__ arguments:

class BasicStarship:
    captain: str = 'Picard'               # instance variable with default
    damage: int                           # instance variable without default
    stats: ClassVar[Dict[str, int]] = {}  # class variable`

    def __init__(self, damage: int, captain: str = None):
        self.damage = damage
        if captain:
            self.captain = captain  # Else keep the default

Lastly, later on in the PEP526 article they say one can do the following for convenience and convention:

class Box(Generic[T]):
    def __init__(self, content):
        self.content: T = content

url to two above code snippets: https://www.python.org/dev/peps/pep-0526/#class-and-instance-variable-annotations

So is one of these conventions better / more widely accepted than the others that I should try to stick to (better readability etc..)?

解决方案

I would recommend using the first version, where you assign types to your __init__ method's parameters, for most circumstances.

That particular method has the least amount of redundancy while still allowing type checkers to verify that you're calling that __init__ method correctly elsewhere in your code.

I would recommend using either the second or third version, where you explicitly annotate your fields (inside or outside __init__) when your __init__ method has grown complex enough to the point where one or more of the following apply:

  1. It's no longer so straightforward what exactly your fields are to begin with
  2. There's no longer a one-to-one mapping between your parameters and your fields
  3. You have complex initialization logic that obscures how your fields are being assigned.

However, it was unclear to me whether the second or third version was preferred -- I personally prefer the third version because it's more conceptually cleaner and doesn't seem to mix the notion of instance vs class attributes, but I can't deny the second version looks cleaner.

I asked about it on the 'typing' gitter channel, and got the following response from Guido (who, on the off-chance you didn't know, made Python and is currently working on mypy and typing related stuff):

There seem to be strong opinions either way. I do indeed prefer putting attribute annotations in the class body rather than sprinkling them throughout __init__ and other methods. I also think that with PEP 526 this will be the future (also with things like class-based NamedTuple declarations and possibly https://github.com/ericvsmith/dataclasses).

(link to quote)

So, it seems like the second version is recommended over the third, and that defining classes in that manner will become more deeply integrated into the Python language itself at some point in the future!

Edit: PEP 557, data classes was recently accepted and appears to be on-track (?) to be included with Python 3.7.

这篇关于实例变量Python的类型提示约定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆