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

我可以向内置Python类型添加自定义方法/属性吗?,python,custom-attributes,monkeypatching,built-in-types,Python,Custom Attributes,Monkeypatching,Built In Types,例如,假设我想在Python的dict类型中添加一个helloWorld()方法。我能做这个吗 JavaScript有一个这样的原型对象。也许这是一个糟糕的设计,我应该对dict对象进行子类化,但它只对子类有效,我希望它能对任何和所有未来的字典起作用 下面是它在JavaScript中的运行方式: String.prototype.hello = function() { alert("Hello, " + this + "!"); } "Jed".hello() //alerts "He

例如,假设我想在Python的dict类型中添加一个
helloWorld()
方法。我能做这个吗

JavaScript有一个这样的原型对象。也许这是一个糟糕的设计,我应该对dict对象进行子类化,但它只对子类有效,我希望它能对任何和所有未来的字典起作用

下面是它在JavaScript中的运行方式:

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

这里有一个有用的链接,提供了更多示例-

是的,通过对这些类型进行子类化。看


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

是的,通过子类化这些类型。看


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

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

这是它的样子

# 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'
"""
#内置名称空间
导入内置__
#扩展子类
类mystr(str):
def first_last(自我):
如果自我:
返回自我[0]+自我[-1]
其他:
返回“”
#用内置命名空间上的子类替换原始str
__内置字符集str=mystr
打印str(1234).first_last()
打印str(0).first_last()
打印str(“”)。first_last()
打印“0”。第一个\最后一个()
输出=”“
14
00
回溯(最近一次呼叫最后一次):
文件“strp.py”,第16行,在
打印“0”。第一个\最后一个()
AttributeError:“str”对象没有“first\u last”属性
"""

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

这是它的样子

# 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'
"""
#内置名称空间
导入内置__
#扩展子类
类mystr(str):
def first_last(自我):
如果自我:
返回自我[0]+自我[-1]
其他:
返回“”
#用内置命名空间上的子类替换原始str
__内置字符集str=mystr
打印str(1234).first_last()
打印str(0).first_last()
打印str(“”)。first_last()
打印“0”。第一个\最后一个()
输出=”“
14
00
回溯(最近一次呼叫最后一次):
文件“strp.py”,第16行,在
打印“0”。第一个\最后一个()
AttributeError:“str”对象没有“first\u last”属性
"""

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

刚刚试过forbbidenfruit

下面是代码,非常简单

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

刚刚尝过禁果

下面是代码,非常简单

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

t h i s   i s   t h e   s t r i n g
H e l l o
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()
输出

t h i s   i s   t h e   s t r i n g
H e l l o
输出

t h i s   i s   t h e   s t r i n g
H e l l o
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()
输出

t h i s   i s   t h e   s t r i n g
H e l l o

注意:此QA标记为“复制到”,但在我看来,它要求的是不同的内容。我不能在那里回答,所以我在这里回答


具体来说,我想从
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
希望这对某人有帮助!干杯,

Andres

注意:此QA标记为重复,但在我看来,它要求的是不同的内容。我不能在那里回答,所以我在这里回答


具体来说,我想从
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
希望这对某人有帮助!干杯,

Andres

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

例如:

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

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

例如:

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

在ruby中也可以通过再次打开类来实现这一点,即:class String;def new_method()。。。;结束;我很确定python也有类似的东西。@Abdullah我相信你指的是猴子修补术,这是大多数人不赞成的。是的,没错。这在Rails中已经完成了。这是特定于
numpy.ndarray
的,但是如果有人来这里尝试这一点,但在尝试向
numpy.ndarray
的实例添加方法时失败,请查看
numpy.ndarray.view
方法。您也可以在ruby中通过简单地再次打开类来实现这一点,即:class String;def new_method()。。。;结束;我很确定python也有类似的东西。@Abdullah我相信你指的是猴子修补术,这是大多数人不赞成的。是的,没错。这是专门针对
numpy.ndarray
的,但是如果有人来这里尝试这个方法,但在尝试向
numpy.ndarray
的实例添加方法时失败了,请看一看