可以暗示一个函数参数不应被修改吗?

huangapple go评论67阅读模式
英文:

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 use Container.

    如果您只是使用中缀in运算符来检查成员身份,您可以使用Container

  • Collection is Iterable plus Container plus the len function.

    Collection包括IterableContainerlen函数。

  • Sequence gives you Collection, __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, the typing module contains the same class names as collections.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 a len? 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 an int and returns a T counts as a Gettable[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 use Container.
  • Collection is Iterable plus Container plus the len function.
  • Sequence gives you Collection, __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

我建议将参数提示为不可变的类型,但可能等效的类型是 tuplefrozenset

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):

huangapple
  • 本文由 发表于 2023年4月17日 10:13:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76031309.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定