Python 中一个类中具有相同名称的方法

发布于 2024-10-18 11:53:19 字数 694 浏览 4 评论 0原文

如何在一个类中声明几个具有相同名称但具有不同数量的参数或不同类型的方法?

在接下来的课程中我必须改变什么?

class MyClass:
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
    def my_method(self,parameter_A_that_Must_Be_String):
        print parameter_A_that_Must_Be_String

    def my_method(self,parameter_A_that_Must_Be_String,parameter_B_that_Must_Be_String):
        print parameter_A_that_Must_Be_String
        print parameter_B_that_Must_Be_String

    def my_method(self,parameter_A_that_Must_Be_String,parameter_A_that_Must_Be_Int):
        print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int

How can I declare a few methods with the same name, but with different numbers of parameters or different types in one class?

What must I change in the following class?

class MyClass:
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
    def my_method(self,parameter_A_that_Must_Be_String):
        print parameter_A_that_Must_Be_String

    def my_method(self,parameter_A_that_Must_Be_String,parameter_B_that_Must_Be_String):
        print parameter_A_that_Must_Be_String
        print parameter_B_that_Must_Be_String

    def my_method(self,parameter_A_that_Must_Be_String,parameter_A_that_Must_Be_Int):
        print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

巾帼英雄 2024-10-25 11:53:20

使用Python 3.5或更高版本,您可以使用@typing.overload为重载函数/方法提供类型注释。

来自文档

@overload
def process(response: None) -> None:
    ...
@overload
def process(response: int) -> tuple[int, str]:
    ...
@overload
def process(response: bytes) -> str:
    ...
def process(response):
    <actual implementation>

Using Python 3.5 or higher, you can use @typing.overload to provide type annotations for overloaded functions/methods.

From the docs:

@overload
def process(response: None) -> None:
    ...
@overload
def process(response: int) -> tuple[int, str]:
    ...
@overload
def process(response: bytes) -> str:
    ...
def process(response):
    <actual implementation>
冰雪之触 2024-10-25 11:53:20

简短的回答:你不能(请参阅之前的讨论)。通常您会使用类似的东西(您可以添加更多类型检查和重新排序):

def my_method(self,parameter_A, parameter_B=None):
  if isinstance(parameter_B, int):
    print parameter_A * parameter_B
  else:
    print parameter_A
    if parameter_B is not None:
      print parameter_B

Short answer: you can't (see this previous discussion). Typically you'd use something like (you could add more type checking and reorder):

def my_method(self,parameter_A, parameter_B=None):
  if isinstance(parameter_B, int):
    print parameter_A * parameter_B
  else:
    print parameter_A
    if parameter_B is not None:
      print parameter_B
爺獨霸怡葒院 2024-10-25 11:53:20

从 Python 3.10 开始,更优雅的解决方案是使用 结构模式匹配

def my_method(parameters):
    match parameters:
        case str():
            # Case 1
        case (str(), str()):
            # Case 2
        case (str(), int()):
            # Case 3
        case _:
            print('no match')

As of Python 3.10 a more elegant solution would be to use Structural Pattern Matching.

def my_method(parameters):
    match parameters:
        case str():
            # Case 1
        case (str(), str()):
            # Case 2
        case (str(), int()):
            # Case 3
        case _:
            print('no match')
音盲 2024-10-25 11:53:20

这是行不通的。无论您有多少个参数,名称 m 都将被第二个 m 方法覆盖。

class C:
    def m(self):
        print('m first')
    def m(self, x):
        print(f'm second {x}')


ci=C();
#ci.m() # will not work TypeError: m() missing 1 required positional argument: 'x'
ci.m(1) # works

输出将很简单:

m second 1

This cannot work. No matter how many arguments you have, the name m will be overriden with the second m method.

class C:
    def m(self):
        print('m first')
    def m(self, x):
        print(f'm second {x}')


ci=C();
#ci.m() # will not work TypeError: m() missing 1 required positional argument: 'x'
ci.m(1) # works

The output will simple be:

m second 1
抱猫软卧 2024-10-25 11:53:20

您可以在Python中尝试多种方法:

http://www.artima.com/weblogs /viewpost.jsp?thread=101605

但我不认为多方法是一种可行的方法。相反,传递给方法的对象应该具有公共接口。您正在尝试实现类似于 C++ 中的方法重载,但在 Python 中很少需要。实现此目的的一种方法是使用 isinstance 级联 ifs,但这很丑陋。

You can try multimethods in Python:

http://www.artima.com/weblogs/viewpost.jsp?thread=101605

But I don't believe multimethod is a way to go. Rather objects that you pass to a method should have common interface. You are trying to achieve method overloading similar to the one in C++, but it is very rarely required in Python. One way to do this is a cascade of ifs using isinstance, but that's ugly.

夜访吸血鬼 2024-10-25 11:53:20

Python 与 Java 完全不同。

没有真正的类型,只有带有方法的对象。

有一种方法可以测试传递的对象是否来自类,但这主要是不好的做法。

但是,您想要为前两个方法生成的代码应该类似于

class MyClass(object):
    def my_method(self, str1, str2=None):
        print str1
        if str2: print str2

第三个方法,那么...使用不同的名称...

Python is nothing like Java.

There are not really types, just objects with methods.

There is a way to test if a passed object is from a class, but it is mainly bad practices.

However, the code you want to produce for the two first methods should be something like

class MyClass(object):
    def my_method(self, str1, str2=None):
        print str1
        if str2: print str2

For the third, well... Use a different name...

淡忘如思 2024-10-25 11:53:20

您可能需要类似于以下的模式:
请注意,在方法名称的开头添加“_”是标记私有方法的约定。

class MyClass:
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
    def my_method(self,parameter_A_that_Must_Be_String, param2=None):
        if type(param2) == str:
            return self._my_method_extra_string_version(parameter_A_that_Must_Be_String, param2)
        elif type(param2) == int:
            return self._my_method_extra_int_version(parameter_A_that_Must_Be_String, param2)
        else:
            pass # use the default behavior in this function
        print parameter_A_that_Must_Be_String

    def _my_method_extra_string_version(self,parameter_A_that_Must_Be_String, parameter_B_that_Must_Be_String):
        print parameter_A_that_Must_Be_String
        print parameter_B_that_Must_Be_String

    def _my_method_extra_int_version(self,parameter_A_that_Must_Be_String, parameter_A_that_Must_Be_Int):
        print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int

You probably want a pattern similar to the following:
Note that adding '_' to the beginning of a method name is convention for marking a private method.

class MyClass:
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
    def my_method(self,parameter_A_that_Must_Be_String, param2=None):
        if type(param2) == str:
            return self._my_method_extra_string_version(parameter_A_that_Must_Be_String, param2)
        elif type(param2) == int:
            return self._my_method_extra_int_version(parameter_A_that_Must_Be_String, param2)
        else:
            pass # use the default behavior in this function
        print parameter_A_that_Must_Be_String

    def _my_method_extra_string_version(self,parameter_A_that_Must_Be_String, parameter_B_that_Must_Be_String):
        print parameter_A_that_Must_Be_String
        print parameter_B_that_Must_Be_String

    def _my_method_extra_int_version(self,parameter_A_that_Must_Be_String, parameter_A_that_Must_Be_Int):
        print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int
少女情怀诗 2024-10-25 11:53:20
class MyClass:
    def __init__(this, foo_str, bar_int):
        this.__foo = foo_str
        this.__bar = bar_int

    def foo(this, new=None):
        if new != None:
            try:
                this.__foo = str(new)
            except ValueError:
                print("Illegal value. foo unchanged.")

        return this.__foo

    def bar(this, new=None):
        if new != None:
            try:
                this.__bar = int(new)
            except ValueError:
                print("Illegal value. bar unchanged.")

        return this.__bar

obj = MyClass("test", 42)
print(obj.foo(), obj.bar())

print(obj.foo("tset"), obj.bar(24))

print(obj.foo(42), obj.bar("test"))

Output:
    test 42
    tset 24
    Illegal value. bar unchanged.
    42 24
class MyClass:
    def __init__(this, foo_str, bar_int):
        this.__foo = foo_str
        this.__bar = bar_int

    def foo(this, new=None):
        if new != None:
            try:
                this.__foo = str(new)
            except ValueError:
                print("Illegal value. foo unchanged.")

        return this.__foo

    def bar(this, new=None):
        if new != None:
            try:
                this.__bar = int(new)
            except ValueError:
                print("Illegal value. bar unchanged.")

        return this.__bar

obj = MyClass("test", 42)
print(obj.foo(), obj.bar())

print(obj.foo("tset"), obj.bar(24))

print(obj.foo(42), obj.bar("test"))

Output:
    test 42
    tset 24
    Illegal value. bar unchanged.
    42 24
苍暮颜 2024-10-25 11:53:20

我认为所有答案中都缺少一个非常简单的例子,那就是:当方法变体之间的唯一区别是参数数量时该怎么办。答案仍然是使用参数数量可变的方法。

假设您从一个需要使用两个参数的方法开始

def method(int_a, str_b):
    print("Got arguments: '{0}' and '{1}'".format(int_a, str_b)

,然后您需要添加一个仅包含第二个参数的变体(例如,因为整数是多余的),解决方案非常简单:

def _method_2_param(int_a, str_b):
    print("Got arguments: '{0}' and '{1}'".format(int_a, str_b))

def _method_1_param(str_b):
    print("Got argument: '{0}'".format(str_b))

def method(*args, **kwargs):
    if len(args) + len(kwargs) == 2:
        return _method_2_param(args, kwargs)
    elif len(args) + len(kwargs) == 1:
        return _method_1_param(args, kwargs)
    else:
        raise TypeError("Method requires one or two arguments")

这个解决方案的好处是没有无论调用代码之前使用关键字参数还是位置参数,它仍然会继续工作。

I think one very simple example is missing from all the answers, and that is: what to do when the only difference between variations on the method is the number of arguments. The answer still is to use a method with variable number of arguments.

Say, you start with a method that requires use of two arguments

def method(int_a, str_b):
    print("Got arguments: '{0}' and '{1}'".format(int_a, str_b)

then you need to add a variant with just the second argument (say, because the integer is redundant), the solution is very simple:

def _method_2_param(int_a, str_b):
    print("Got arguments: '{0}' and '{1}'".format(int_a, str_b))

def _method_1_param(str_b):
    print("Got argument: '{0}'".format(str_b))

def method(*args, **kwargs):
    if len(args) + len(kwargs) == 2:
        return _method_2_param(args, kwargs)
    elif len(args) + len(kwargs) == 1:
        return _method_1_param(args, kwargs)
    else:
        raise TypeError("Method requires one or two arguments")

The nice thing about this solution is that no matter if the calling code used keyword arguments or positional arguments before, it will still continue to work.

肥爪爪 2024-10-25 11:53:20

我认为 @overload 解决了这个问题:VS Code -> open() 上的 f12 ->它显示了 open() 函数的一堆重复项:

@overload
def open(...):
@overload
def open(...):
...

所以,这就是结果......

from typing import overload

class MyClass:
""""""

#----------------------------------------------------------------------
def __init__(self):
    """Constructor"""
@overload
def my_method(self,parameter_A_that_Must_Be_String,parameter_B_that_Must_Be_String):
    print parameter_A_that_Must_Be_String
    print parameter_B_that_Must_Be_String
@overload
def my_method(self,parameter_A_that_Must_Be_String,parameter_A_that_Must_Be_Int):
    print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int
def my_method(self,parameter_A_that_Must_Be_String):
    print parameter_A_that_Must_Be_String

抱歉我有点紧张......

I think @overload solves the thing: VS Code -> f12 on open() -> it shows a bunch of duplicates of the open() function:

@overload
def open(...):
@overload
def open(...):
...

So, here's the result...

from typing import overload

class MyClass:
""""""

#----------------------------------------------------------------------
def __init__(self):
    """Constructor"""
@overload
def my_method(self,parameter_A_that_Must_Be_String,parameter_B_that_Must_Be_String):
    print parameter_A_that_Must_Be_String
    print parameter_B_that_Must_Be_String
@overload
def my_method(self,parameter_A_that_Must_Be_String,parameter_A_that_Must_Be_Int):
    print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int
def my_method(self,parameter_A_that_Must_Be_String):
    print parameter_A_that_Must_Be_String

I'm sorry for being nervous...

﹏雨一样淡蓝的深情 2024-10-25 11:53:20

您可以使用 multipledispatch.dispatchtyping.overload 优雅地完成此操作,而不是使用丑陋的 isinstance(b, str)*参数

安装:pip3 install multipledispatch

from typing import overload
from multipledispatch import dispatch

# Annotations of mulitple input options for better visual.
@overload
def func(a:str): pass
@overload
def func(a:str, b:str): pass
@overload
def func(a:str, b:int): pass

# Actuall implementations for different sets of input.
@dispatch(str)
def func(a):
    print("ha")
@dispatch(str, str)
def func(a,b):
    print("haha")
@dispatch(str, int)
def func(a,b):
    print("hahaha")

func("a")
func("a","b")
func("a",1)

你得到:

ha
haha
hahaha

使用@overload,你将看到输入选项的提示:
输入图片此处描述

在此处输入图像描述

没有@overload,它仍然有效,但没有提示:
输入图片此处描述

You can use multipledispatch.dispatch and typing.overload to do that ellegantly instead of using ugly isinstance(b, str) or *args.

Install: pip3 install multipledispatch

from typing import overload
from multipledispatch import dispatch

# Annotations of mulitple input options for better visual.
@overload
def func(a:str): pass
@overload
def func(a:str, b:str): pass
@overload
def func(a:str, b:int): pass

# Actuall implementations for different sets of input.
@dispatch(str)
def func(a):
    print("ha")
@dispatch(str, str)
def func(a,b):
    print("haha")
@dispatch(str, int)
def func(a,b):
    print("hahaha")

func("a")
func("a","b")
func("a",1)

You get:

ha
haha
hahaha

With @overload, you will see the hints of input options:
enter image description here

and

enter image description here

Without @overload, it still works, but no hints:
enter image description here

信愁 2024-10-25 11:53:19

您可以拥有一个接受可变数量参数的函数。

def my_method(*args, **kwds):
    # Do something

# When you call the method
my_method(a1, a2, k1=a3, k2=a4)

# You get:
args = (a1, a2)
kwds = {'k1':a3, 'k2':a4}

所以你可以修改你的函数如下:

def my_method(*args):
    if len(args) == 1 and isinstance(args[0], str):
        # Case 1
    elif len(args) == 2 and isinstance(args[1], int):
        # Case 2
    elif len(args) == 2 and isinstance(args[1], str):
        # Case 3

You can have a function that takes in a variable number of arguments.

def my_method(*args, **kwds):
    # Do something

# When you call the method
my_method(a1, a2, k1=a3, k2=a4)

# You get:
args = (a1, a2)
kwds = {'k1':a3, 'k2':a4}

So you can modify your function as follows:

def my_method(*args):
    if len(args) == 1 and isinstance(args[0], str):
        # Case 1
    elif len(args) == 2 and isinstance(args[1], int):
        # Case 2
    elif len(args) == 2 and isinstance(args[1], str):
        # Case 3
音栖息无 2024-10-25 11:53:19

你不能。没有重载或多重方法或类似的东西。一个名字指的是一件事。无论如何,就语言而言,您始终可以自己模拟它们...您可以使用isinstance检查类型(但请正确执行 - 例如在Python 2中,使用 basestring 来检测字符串和 unicode),但它很丑陋,通常不鼓励并且很少有用。如果这些方法执行不同的操作,请为它们指定不同的名称。还要考虑多态性。

You can't. There are not overloads or multimethods or similar things. One name refers to one thing. As far as the language is concerned anyway, you can always emulate them yourself... You could check types with isinstance (but please do it properly - e.g. in Python 2, use basestring to detect both strings and unicode), but it's ugly, generally discouraged and rarely useful. If the methods do different things, give them different names. Consider polymorphism as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文