【发布时间】:2019-07-23 14:57:02
【问题描述】:
当我动态设置一个类的属性时:
from typing import TypeVar, Generic, Optional, ClassVar, Any
class IntField:
type = int
class PersonBase(type):
def __new__(cls):
for attr, value in cls.__dict__.items():
if not isinstance(value, IntField):
continue
setattr(cls, attr, value.type())
return cls
class Person(PersonBase):
age = IntField()
person = Person()
print(type(Person.age)) # <class 'int'>
print(type(person.age)) # <class 'int'>
person.age = 25 # Incompatible types in assignment (expression has type "int", variable has type "IntField")
age 属性的类型将是 int 类型,但 MyPy 不能遵循该类型。
有没有办法让 MyPy 理解?
Django 已经实现了:
from django.db import models
class Person(models.Model):
age = models.IntegerField()
person = Person()
print(type(Person.age)) # <class 'django.db.models.query_utils.DeferredAttribute'>
print(type(person.age)) # <class 'int'>
person.age = 25 # No error
Django 是如何做到这一点的?
【问题讨论】:
-
我不确定 Django,但这种模式经常使用 descriptors 实现。
-
type(Person.age)在每种情况下是什么? -
@jdehesa 我将打印结果放在评论中。在这两种情况下都是
<class 'int'>。 -
不,我的意思是
Person.age,是类属性,而不是实例。 -
我的错。我添加到sn-ps。有趣的是,在我的例子中,它在实例化之前已经是一个 int 了。
标签: python python-3.x metaprogramming type-hinting