【问题标题】:Static overloaded method in Python class. Missing argument issuePython 类中的静态重载方法。缺少论据问题
【发布时间】:2015-10-08 20:02:51
【问题描述】:

我有一个类 db 定义如下:

class db:

    def __init_(self, idx, host, port, db_name, user, password):
        self.idx = idx
        ...

    def Connect(self):
        conn = db_engine.connect(host=self.host, ...)

    @staticmethod
    def Connect(idx):
        if idx == 1:
            d = db(1, "localhost", 80, ...)
            conn = d.Connect()
        return conn

所以,如您所见,我的班级有两种方法。最重要的是它有一个静态方法Connect,它在内部尝试调用一个非静态方法Connect。但是,当我尝试使用我的程序时,我收到一条错误消息:

d.Connect()

TypeError: Connect() 缺少 1 个必需的位置参数 ...

似乎静态方法试图调用自己,但是我想让它调用另一个非静态方法。那么,我做错了什么?

【问题讨论】:

    标签: python python-3.x static-methods


    【解决方案1】:

    重新定义了Count 方法。 Python 不支持重载;您不能同时定义常规方法和静态方法。您只有拥有 staticmethod 版本,因为它是最后定义的,它完全取代了非静态版本。

    如果你需要一个方法来改变它的行为是否基于它是否被绑定(静态与常规方法),你有两个选择;要么测试self 参数的类型(它将是一个整数或db 类的一个实例),或者你必须构建一个自定义的descriptor object,它可以改变你的方法被调用的方式上下文;在实例或类上。

    测试self 的类型如下所示:

    class db:
        def __init_(self, idx, host, port, db_name, user, password):
            self.idx = idx
            # ...
    
        def Connect(self_or_idx):
            if isinstance(self_or_idx, db):
                self = self_or_idx
                conn = db_engine.connect(host=self.host, ...)
                # ...
            else:
                idx = self_or_idx
                if idx == 1:
                    d = db(1, "localhost", 80, ...)
                    conn = d.Connect()
                return conn
    

    如果使用自定义描述符,您可以构建一个支持两种不同功能的描述符like the property object does

    class static_or_instance_method(object):
        def __init__(self, instancemethod=None, staticmethod=None):
            self.method = instancemethod
            self.static = staticmethod
    
        def staticmethod(self, staticmethod):
            return type(self)(self.method, staticmethod)
    
        def instancemethod(self, instancemethod):
            return type(self)(instancemethod, self.static)
    
        def __get__(self, instance, cls=None):
            if instance is None:
                return self.static
            return self.method.__get__(instance, cls)
    

    然后像这样使用它:

    class db:
        def __init_(self, idx, host, port, db_name, user, password):
            self.idx = idx
            # ...
    
        @static_or_instance_method
        def Connect(self):
            conn = db_engine.connect(host=self.host, ...)
            # ...
    
        @Connect.staticmethod
        def Connect(idx):
            if idx == 1:
                d = db(1, "localhost", 80, ...)
                conn = d.Connect()
            return conn
    

    描述符的快速演示:

    >>> class Foo:
    ...     @static_or_instance_method
    ...     def bar(self):
    ...         return 'Bound method of {}'.format(self)
    ...     @bar.staticmethod
    ...     def bar(arg):
    ...         return 'Static method, receiving argument {}'.format(arg)
    ... 
    >>> Foo().bar()
    'Bound method of <__main__.Foo object at 0x10b6cf588>'
    >>> Foo.bar('spam')
    'Static method, receiving argument spam'
    

    【讨论】:

    • 顺便说一句。有一个小错误。在else 块中应该返回d,而不是conn
    • @Jacobian:我直接基于您自己的staticmethod 代码在您的问题中。此外,对于手头的问题(如何处理在类或实例上调用方法),这里究竟返回什么并不重要。 :-)
    猜你喜欢
    • 2011-06-29
    • 2017-06-28
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多