英文:
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
inoperator to check for membership, you can useContainer.如果您只是使用中缀
in运算符来检查成员身份,您可以使用Container。 -
CollectionisIterableplusContainerplus thelenfunction.Collection包括Iterable、Container和len函数。 -
Sequencegives 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.abcclasses were non-generic. If you need to be compatible with Python versions prior to that, thetypingmodule 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 anintand returns aTcounts 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
inoperator to check for membership, you can useContainer. CollectionisIterableplusContainerplus thelenfunction.Sequencegives 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):
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论