英文:
Is it possible to hint that a function parameter should not be modified?
问题
以下是您要翻译的内容:
例如,我可能会有一个包含一些抽象方法的抽象基类,该方法将某种可变类型作为参数:
from abc import *
class AbstractClass(metaclass=ABCMeta):
@abstractmethod
def abstract_method(self, mutable_parameter: list | set):
raise NotImplementedError
是否有一种方式可以提示给函数实现者,这个参数在该方法的任何实现中都不应被修改?
我想象中可能会有类似ReadOnly
的东西存在:
def abstract_method(self, mutable_parameter: ReadOnly[list]):
但我似乎找不到任何暗示这种东西存在的线索。
从查看类型模块文档来看,我本以为Final
就是我要找的,但PyCharm告诉我“无法在函数参数的注释中使用'Final'”。
英文:
For example, I might have an abstract base class with some abstract method that takes some mutable type as a parameter:
from abc import *
class AbstractClass(metaclass=ABCMeta):
@abstractmethod
def abstract_method(self, mutable_parameter: list | set):
raise NotImplementedError
Is there some way of hinting to the function implementer that this parameter should not be modified in any implementation of this method?
I imagine maybe something like ReadOnly
could exist:
def abstract_method(self, mutable_parameter: ReadOnly[list]):
but I can't seem to find anything suggesting such a thing does exist.
From looking at the typing module docs I would have assumed that Final
was what I am looking for but PyCharm tells me 'Final' could not be used in annotations for function parameters
.
答案1
得分: 3
以下是您要翻译的内容:
-
You might be able to find a structural superclass that provides the behaviors you want. There's a good summary of the available collections classes at
collections.abc
,but as a quick, non-exhaustive summary.也许您可以找到一个提供所需行为的结构超类。在
collections.abc
中有可用集合类的良好摘要,但这只是一个快速的、非详尽的摘要。 -
If you're just planning to iterate over the collection in some order, you're looking for
Iterable
.如果您只打算按某种顺序遍历集合,您需要的是
Iterable
。 -
If all you're doing is using the infix
in
operator to check for membership, you can useContainer
.如果您只是使用中缀
in
运算符来检查成员身份,您可以使用Container
。 -
Collection
isIterable
plusContainer
plus thelen
function.Collection
包括Iterable
、Container
和len
函数。 -
Sequence
gives youCollection
,__getitem__
(i.e. the square brackets operator), and several other nice list-y things. This is a good general-purpose candidate for list-like structures.Sequence
提供了Collection
、__getitem__
(即方括号操作符)和其他一些有用的列表功能。这是适用于类似列表的结构的通用候选项。 -
None of these protocols have any mutating methods, so if you adhere strictly to your types (and don't downcast), then you can be assured that a function taking these types will not mutate the argument.
这些协议都没有任何可变方法,因此如果您严格遵循您的类型(并且不进行向下转型),那么您可以确保接受这些类型的函数不会更改参数。
-
Note that, prior to PEP 585 (released in Python 3.9), the
collections.abc
classes were non-generic. If you need to be compatible with Python versions prior to that, thetyping
module contains the same class names ascollections.abc
, and those were generic since day one.请注意,在PEP 585(发布于Python 3.9之前)之前,
collections.abc
类是非泛型的。如果您需要与之前的Python版本兼容,typing
模块包含与collections.abc
相同的类名,并且这些类从一开始就是泛型的。 -
And, finally, the glory of structural superclasses is that you can define them anytime with
typing.Protocol
. If you can't find a protocol that suits your needs, then just make one. Are you planning to call__getitem__
but want to support structures that don't have alen
? Here's your protocol!最后,结构超类的优势在于您随时可以使用
typing.Protocol
来定义它们。如果找不到适合您需求的协议,那就自己创建一个。您计划调用__getitem__
,但希望支持没有len
的结构吗?这就是您的协议!
from typing import Protocol, TypeVar
T = TypeVar("T", covariant=True)
class Gettable(Protocol[T]):
def __getitem__(self, index: int, /) -> T:
...
-
Since this class inherits from
Protocol
, when used in type hints it will behave as a structural subtype, meaning any object which has a__getitem__
that takes anint
and returns aT
counts as aGettable[T]
, even without an explicit runtime subtyping relationship.由于这个类继承自
Protocol
,在类型提示中使用时,它将表现为结构子类型,这意味着任何具有接受int
并返回T
的__getitem__
的对象都被视为Gettable[T]
,即使没有明确的运行时子类型关系。
英文:
You might be able to find a structural superclass that provides the behaviors you want. There's a good summary of the available collections classes at collections.abc
, but as a quick, non-exhaustive summary.
- If you're just planning to iterate over the collection in some order, you're looking for
Iterable
. - If all you're doing is using the infix
in
operator to check for membership, you can useContainer
. Collection
isIterable
plusContainer
plus thelen
function.Sequence
gives youCollection
,__getitem__
(i.e. the square brackets operator), and several other nice list-y things. This is a good general-purpose candidate for list-like structures.
None of these protocols have any mutating methods, so if you adhere strictly to your types (and don't downcast), then you can be assured that a function taking these types will not mutate the argument.
Note that, prior to PEP 585 (released in Python 3.9), the collections.abc
classes were non-generic. If you need to be compatible with Python versions prior to that, the typing
module contains the same class names as collections.abc
, and those were generic since day one.
And, finally, the glory of structural superclasses is that you can define them anytime with typing.Protocol
. If you can't find a protocol that suits your needs, then just make one. Are you planning to call __getitem__
but want to support structures that don't have a len
? Here's your protocol!
from typing import Protocol, TypeVar
T = TypeVar("T", covariant=True)
class Gettable(Protocol[T]):
def __getitem__(self, index: int, /) -> T:
...
Since this class inherits from Protocol
, when used in type hints it will behave as a structural subtype, meaning any object which has a __getitem__
that takes an int
and returns a T
counts as a Gettable[T]
, even without an explicit runtime subtyping relationship.
答案2
得分: 1
我建议将参数提示为不可变的类型,但可能等效的类型是 tuple
或 frozenset
。
def abstract_method(immutable_parameter: tuple | frozenset):
英文:
I'd suggest hinting the parameter as the immutable, but likely equivalent types tuple
or frozenset
def abstract_method(immutable_parameter: tuple | frozenset):
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论