繁体   English   中英

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

[英]Can I add custom methods/attributes to built-in Python types?

例如——假设我想向 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

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

这是它的样子

# 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'
"""

刚试过禁果!

这是代码,非常简单!

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

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

例如:

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

:本QA被标记为复制到这一个,但IMO它要求不同的东西。 我无法在那里回答,所以我在这里回答。


具体来说,我想从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

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

是的,通过子类化这些类型。 请参阅在 Python 中统一类型和类

不,这并不意味着实际的 dicts 会有这种类型,因为那会令人困惑。 对内置类型进行子类化是添加功能的首选方式。

class MyString:
    def __init__(self, string):
        self.string = string
    def bigger_string(self):
        print(' '.join(self.string))

mystring = MyString("this is the string")
mystring.bigger_string()

输出

t h i s   i s   t h e   s t r i n g

Python 3.7 中的数据类

from dataclasses import dataclass

@dataclass
class St:

    text : str

    def bigger(self) -> None:
        self.text = list(self.text)
        print(" ".join(self.text))

mys = St("Hello")
mys.bigger()

输出

H e l l o

是的,我们可以为内置的 Python 类型添加自定义方法和属性。 例如,假设您想在列表类中定义一个新方法。

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

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'类的属性/成员,你可以定义自己的方法或属性。 因此,通过这种方式,您可以使用相同的类名调用用户定义的/内置的类方法。

这是它的外观:

#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(self, value)的原始功能将会丢失。

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

例如,您可以像下面这样声明一个类,它不会引发任何错误,否则您将不会面临任何命名冲突。

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)

子类化是 Python 的方式。 多语言程序员学会在正确的情况下使用正确的工具 - 在合理范围内。 像 Rails(一种使用 Ruby 的 DSL)这样巧妙构建的东西很难用像 Python 这样语法更严格的语言来实现。 人们经常比较这两者,说它们有多相似。 这种比较有点不公平。 Python 以自己的方式发光。 托奇托。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM