我可以向内置 Python 类型添加自定义方法/属性吗?
- 2025-01-20 09:07:00
- admin 原创
- 92
问题描述:
例如,假设我想helloWorld()
向 Python 的 dict 类型添加一个方法。我可以这样做吗?
JavaScript 有一个原型对象,其行为方式如下。也许这是个糟糕的设计,我应该将 dict 对象子类化,但它只适用于子类,而我希望它适用于任何未来的字典。
在 JavaScript 中,其运行方式如下:
String.prototype.hello = function() {
alert("Hello, " + this + "!");
}
"Jed".hello() //alerts "Hello, Jed!"
这里有一个有用的链接,其中包含更多示例 - http://www.javascriptkit.com/javatutors/proto3.shtml
解决方案 1:
您无法直接将方法添加到原始类型。但是,您可以对类型进行子类化,然后在内置/全局命名空间中替换它,这可以实现所需的大部分效果。不幸的是,通过文字语法创建的对象将继续是原始类型,并且不会具有您的新方法/属性。
它看起来是这样的
# 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'
"""
解决方案 2:
刚刚尝试了禁果!
这是代码,非常简单!
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()
解决方案 3:
注意:此 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
希望这对某人有帮助!谢谢,
安德烈斯
解决方案 4:
确实如此,但是您必须定义一个相同类型的新类,并且它应该从该类型继承。
例如:
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))
解决方案 5:
是的,我们可以向内置 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”作为类名的类时,您将不再能够访问“内置列表”类方法,因为“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]。
注意:但是当你这样做时,从长远来看可能会产生一些歧义问题,例如命名冲突
例如,如果您有一个方法,其签名与用户定义类中的内置函数(此处为“list”)相同,那么它将在您不知情或未注意到的情况下被覆盖,因此您将来可能无法使用其原始功能。考虑上述代码,如果您定义了类似 的方法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)
解决方案 6:
要将自定义方法和属性添加到列表:
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)
解决方案 7:
是的,通过对这些类型进行子类化。请参阅在 Python 中统一类型和类。
不,这并不意味着实际的字典会有这种类型,因为那会造成混淆。子类化内置类型是添加功能的首选方法。
解决方案 8:
子类化是 Python 的必由之路。通晓多种语言的程序员学会在合理的情况下使用正确的工具。像 Rails(使用 Ruby 的 DSL)这样精心构建的东西在 Python 这样语法更严格的语言中实现起来非常困难。人们经常将两者进行比较,说它们有多么相似。这种比较有点不公平。Python 以自己的方式闪耀着光芒。totochto。
解决方案 9:
TL;DR
编辑源代码。
完整解释如果您了解 C,您可以通过分叉Python 存储库并更改Objects 文件夹中所需的文件
来更改函数方法。然后,阅读文件以获取构建说明。README.rst