我可以向内置 Python 类型添加自定义方法/属性吗?

问题描述 投票:0回答:9

例如,假设我想向 Python 的 dict 类型添加一个

helloWorld()
方法。我可以这样做吗?

JavaScript 有一个以这种方式运行的原型对象。也许这是糟糕的设计,我应该对 dict 对象进行子类化,但它只适用于子类,我希望它适用于任何和所有未来的词典。

在 JavaScript 中它是这样的:

String.prototype.hello = function() {
    alert("Hello, " + this + "!");
}
"Jed".hello() //alerts "Hello, Jed!"

这里有一个有用的链接,其中包含更多示例 - http://www.javascriptkit.com/javatutors/proto3.shtml

python custom-attributes monkeypatching built-in-types
9个回答
103
投票

不能直接将方法添加到原始类型中。但是,您可以对该类型进行子类化,然后在内置/全局命名空间中替换它,这可以实现大部分所需的效果。不幸的是,通过文字语法创建的对象将继续是普通类型,并且不会具有新的方法/属性。

这就是它的样子

# Built-in namespace
import __builtin__

# Extended subclass
class mystr(str):
    def first_last(self):
        if self:
            return self[0] + self[-1]
        else:
            return ''

# Substitute the original str with the subclass on the built-in namespace    
__builtin__.str = mystr

print str(1234).first_last()
print str(0).first_last()
print str('').first_last()
print '0'.first_last()

output = """
14
00

Traceback (most recent call last):
  File "strp.py", line 16, in <module>
    print '0'.first_last()
AttributeError: 'str' object has no attribute 'first_last'
"""

10
投票

刚刚尝试了禁果!

这是代码,很简单!

from forbiddenfruit import curse


def list_size(self):
    return len(self)

def string_hello(self):
    print("Hello, {}".format(self))

if __name__ == "__main__":
    curse(list, "size", list_size)
    a = [1, 2, 3]
    print(a.size())
    curse(str, "hello", string_hello)
    "Jesse".hello()

8
投票

确实是的,但是你必须定义一个相同类型的新类,并且它应该继承自该类型。

例如:

class list(list):
    def __init__(self, *args):
        super().__init__(args)
    def map(self, function):
        return [function(i) for i in self]

a = list(1, 2, 3, 4, 5)

def double(i):
    return i * 2

print(a.map(double))

8
投票

注意:此 QA 被标记为与 this 重复,但在我看来,它要求不同的东西。我无法在那里回答,所以我在这里回答。


具体来说,我想继承

str
并添加自定义属性。现有的答案(尤其是那些说你“不能”的答案)并没有完全解决这个问题,但这对我有用: class TaggedString(str): """ A ``str`` with a ``.tags`` set and ``.kwtags`` dict of tags. Usage example:: ts = TaggedString("hello world!", "greeting", "cliche", what_am_i="h4cker") (ts.upper(), ts.tags, ts.kwtags) """ def __new__(cls, *args, **kwargs): return super().__new__(cls, args[0]) def __init__(self, s, *tags, **kwtags): super().__init__() self.tags = set(tags) self.kwtags = kwtags

希望这对某人有帮助!干杯,
安德烈斯



3
投票

让我们考虑定义一个“列表”类并编写自己的函数,如下所示:

class list: def custom_method (self): return("Hey, I'm a custom method of list class") #lets create an object here obj = list([1,2,3]) print(obj.custom_method()) #The above runs fine, but a list has append() method also right?? let's try it print(obj.append(1)) """Now you will get Attribute error : list object has no attribute append()"""

因为,当您定义以“list”作为类名的类时,您将无法再访问“内置列表”类方法,因为“列表”被视为用户定义的类而不是内置类。 

因此,为了摆脱这个错误,您可以继承“list”类的属性/成员,并且可以定义自己的方法或属性。因此,通过这种方式,您可以使用相同的类名调用用户定义/内置的类方法。

它看起来是这样的:

#Extending in-built list class class list(list): def custom_method (self): return("Hey, I'm a custom method of list class") obj = list([1,2,3]) print(obj.custom_method()) obj.append(1) print(obj)

它运行良好,并将修改后的列表输出为 [1,2,3,1]。

注意:

但是当你这样做时,从长远来看可能会产生一些歧义问题,例如命名冲突

例如,如果您有一个与用户定义的类中的内置函数具有相同签名的方法(此处为“列表”),那么它将在您不知情或不知情的情况下被覆盖,因此您可能无法使用其未来的原始功能。考虑到上面的代码,如果你定义了像

append(self, value)

这样的方法,append() 的原始功能将会丢失。

因此,最好使用不同的类名作为类名,而不是与内置类名相同

例如,您可以如下声明一个类,这样不会引发任何错误,也不会遇到任何命名冲突。

class custom_list(list): def custom_method (self): return("Hey, I'm a custom method of list class") obj = custom_list([1,2,3]) print(obj.custom_method()) obj.append(1) print(obj)



1
投票
统一 Python 中的类型和类

不,这并不意味着实际的字典将具有这种类型,因为这会令人困惑。子类化内置类型是添加功能的首选方法。


1
投票
TL;博士

编辑源代码。

完整说明

如果您了解 C,则可以通过分叉 Python 存储库
并更改 Objects 文件夹 中所需的文件来更改函数方法。然后,阅读 README.rst 文件以获取构建说明。

    


0
投票

import gc dikt=gc.get_referents(list.__dict__)[0] dikt['length']= property(lambda self: len(self)) # length attribute def push(self,data):self+=[data] dikt['push']= push # push method a=[1,2,3] print(a.length) a.push(4) print(a.length) print(a)



-2
投票

© www.soinside.com 2019 - 2024. All rights reserved.