我正在查看PEP 484,但找不到有关如何键入提示类引用的说明。类引用是否声明为 Callables,如下所示?
from typing import Callable
class SomeClass:
def __init__(self):
self.s = 'Hello'
def display(self):
print(self.s)
x: Callable[[], SomeClass] = SomeClass
instance = x()
instance.display()
Run Code Online (Sandbox Code Playgroud)
谢谢!
我查看了一些与使用带有描述符的打字相关的 SO 帖子和 github 问题,但我无法解决我的问题。
我有包装类,我想将属性定义为可以获取和“转换”内部数据结构的属性的描述。
class DataDescriptor(object):
def __init__(self, name: str, type_):
self.name = name
self.type_ = type_
def __get__(self, instance, cls):
if not instance:
raise AttributeError("this descriptor is for instances only")
value = getattr(instance._data, self.name)
return self.type_(value)
class City(object):
zip_code: str = DataDescriptor("zip_code", str)
# mypy: Incompatible types in assignment
population: float = DataDescriptor("population", float)
# mypy: Incompatible types in assignment
def __init__(self, data):
self._data = data
class InternalData:
# Will be consumed through city wrapper
def __init__(self): …Run Code Online (Sandbox Code Playgroud) 我开始在 python 3.6 中进入类型提示(又名注释),我无法弄清楚这个特性的一些动态方面。
我写了下面的一段代码,我想添加注释但不确定如何,即使在查看了关于类型提示的文档之后也是如此。
这是函数:
def validate_expression(expression: ?):
try:
assert expression
except AssertionError as e:
...
Run Code Online (Sandbox Code Playgroud)
expression需要是断言起作用的任何东西(假设任何表达式bool(expression)都是有效的)。
我应该写什么来代替问号?
更新:
我知道大多数 python 表达式都可以转换为布尔值,但是我编写此代码的上下文是合理期望表达式不可断言的上下文。
在我的案例中的相关示例是pandas.DataFrame. 运行
bool(pandas.DataFrame())会引发错误,我有充分的理由期望有人可能会尝试将数据帧传递给验证函数。
更新 2:
按照Chepner的评论和回答,我现在明白了: 1. 在绝大多数情况下,任何 python 表达式都将有效地转换为布尔值,这要么被覆盖,typing.Any要么根本不添加注释。2. 在我感兴趣的边缘情况下,即bool(pandas.DataFrame()) # --> ValueError注释无济于事,因为这是一个运行时错误。3.如果还有另一个与静态类型提示相关的边缘情况,我不知道。4. 考虑到相关示例的稀有性/不存在性,没有开箱即用的类型一般只描述被强制转换为布尔值的能力的质量(类似于typing.Iterable),并且就我而言,不值得向后弯腰来解决这种边缘情况(尽管听到相关示例和弯曲解决方案会很有趣!)
我试图用@overload不同的方式来传达调用函数的不同方式,但是在代码中用简单的else语句轻松传达的内容在类型注释中是不可能的。如果没有“else”,MyPy(正确地)会抱怨重载版本不匹配(例如,请参见下面的代码段)。
error: Overloaded function signatures 1 and 2 overlap with incompatible return types
我是否正确理解此问题没有好的解决方案?
例如。这是一个简单的例子:
ListOrTuple = TypeVar("ListOrTuple", List, Tuple)
# unfortunately, typing doesn't support "anything else" at the moment
# https://github.com/python/typing/issues/599#issuecomment-586007066
AnythingElse = TypeVar("AnythingElse")
# what I would like to have is something like AnythingElse= TypeVar("AnythingElse", Not[List,Tuple])
@overload
def as_list(val: ListOrTuple) -> ListOrTuple:
...
@overload
def as_list(val: AnythingElse) -> List[AnythingElse]:
...
def as_list(val):
"""Return list/tuple as is, otherwise wrap in a list
>>> as_list("test")
['test'] …Run Code Online (Sandbox Code Playgroud) 更新:尝试检查/填充另一个函数中的值
我正在尝试在我的项目中使用 mypy,但是我使用的许多实例属性仅在 之后初始化__init__,而不是在其中初始化。但是,我确实希望保持在 处声明所有实例属性的良好做法__init__,因此我需要一些复杂的解决方案来完成这项工作。
我希望它如何表现的一个例子(目前 mypy 正在抱怨):
from typing import Optional
class Foo:
def __init__(self, x: int):
self.x = x
self.y: int = None # will initialize later, but I know it will be an int
def fill_values(self):
self.y = x**2
def do(self) -> int:
return self.x + self.y
Run Code Online (Sandbox Code Playgroud)
目前 mypy 抱怨 的分配self.y,并希望它是Optionalor None。
如果我同意并将该行更改为self.y: Optional[int] = None,则 mypy 会抱怨 的返回值do,因为self.y可能是None. …
我想在 Python 中创建等价物:
static class Event {}
static class MyEvent extends Event {}
interface Filter<E extends Event> {
boolean filter(E event);
}
static class MyFilter implements Filter<MyEvent> {
@Override public boolean filter(MyEvent event) {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的尝试(mypy-play):
from typing import TypeVar, Protocol
class Event:
pass
class MyEvent(Event):
pass
E = TypeVar("E", bound=Event)
class Filter(Protocol[E]):
def filter(self, event: E) -> bool:
raise NotImplementedError
class MyFilter(Filter):
def filter(self, event: MyEvent) -> bool: # should be ok
raise NotImplementedError …Run Code Online (Sandbox Code Playgroud) 假设我定义了一个新类型:
import typing
Index = typing.NewType('Index', int)
Run Code Online (Sandbox Code Playgroud)
然后假设我有一个Index变量:
index = Index(0)
Run Code Online (Sandbox Code Playgroud)
增量的惯用方法是index什么?
如果我做
index += 1
Run Code Online (Sandbox Code Playgroud)
这相当于
index = index + 1
Run Code Online (Sandbox Code Playgroud)
那么类型index变为int而不是Index从静态类型检查的角度来看:
$ mypy example.py
Run Code Online (Sandbox Code Playgroud)
example.py:4: error: Incompatible types in assignment (expression has type "int", variable has type "Index")
Run Code Online (Sandbox Code Playgroud)
有什么比
index = Index(index + 1)
Run Code Online (Sandbox Code Playgroud)
保持Index类型?
我在 python 中遇到了联合(和 Optionals,当然)有点奇怪 - 即似乎静态类型检查器针对联合的所有成员测试属性,而不是联合的成员(即似乎过分严格?)。例如,请考虑以下情况:
import pandas as pd
def test_dummy() -> pd.DataFrame:
df = pd.DataFrame()
df = df.fillna(df)
return df
Run Code Online (Sandbox Code Playgroud)
这会创建一个类型警告,因为pd.fillna(..., inplace: Bool = False, ...) -> Optional[pd.DataFrame](它是一个None返回 if inplace=True)。我怀疑理论上静态类型检查器应该根据参数实现函数的返回变化(因为在编写代码时应该知道),但这有点过分了。
我有以下问题:
解决此问题的最佳方法是什么?我可以想到两种解决方案:
i) 什么都不做——这会在我的代码中产生丑陋的波浪线
ii)cast返回fillna到 a pd.DataFrame;我的理解是这是静态类型检查器的信息性步骤,因此不应引起任何担忧或问题?
让我们考虑一下我正在编写一个f与此类似的函数,它的返回类型因函数调用输入而异,并且这应该在运行时之前就可以确定。为避免日后发生此类错误;编写此函数的最佳方法是什么?做类似的事情会更好@typing.overload吗?
谢谢!
我遇到了这个静态类型提示不匹配(使用 Pyright):
from __future__ import annotations
from typing import AnyStr, Iterable
def foo(i: Iterable[AnyStr]):
return i
def bar(i: Iterable[str] | Iterable[bytes]):
return i
def baz(i: Iterable[str | bytes]):
return i
def main():
s = ['a']
# makes sense to me
baz(foo(s)) # allowed
foo(baz(s)) # not allowed
# makes sense to me
baz(bar(s)) # allowed
bar(baz(s)) # not allowed
bar(foo(s)) # allowed
foo(bar(s)) # nope -- why?
Run Code Online (Sandbox Code Playgroud)
什么之间的区别Iterable[AnyStr]和Iterable[str] | Iterable[bytes]?
它们不应该是“等效的”吗?(除了AnyStr在上下文中引用单个一致类型)
更具体地说:键入提示以下内容的正确方法是什么?
import random …Run Code Online (Sandbox Code Playgroud) python ×10
python-typing ×10
mypy ×3
python-3.x ×3
type-hinting ×2
covariance ×1
pandas ×1
typeshed ×1