[英]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.