Sha*_*kan 23 python extension-methods
好的,在c#中我们有类似的东西:
public static string Destroy(this string s) {
return "";
}
Run Code Online (Sandbox Code Playgroud)
所以基本上,当你有一个字符串,你可以做:
str = "This is my string to be destroyed";
newstr = str.Destroy()
# instead of
newstr = Destroy(str)
Run Code Online (Sandbox Code Playgroud)
现在这很酷,因为在我看来它更具可读性.python有类似的东西吗?我的意思是代替写这样的:
x = SomeClass()
div = x.getMyDiv()
span = x.FirstChild(x.FirstChild(div)) # so instead of this
Run Code Online (Sandbox Code Playgroud)
有什么建议吗?
Dav*_*nan 19
您可以直接修改类,有时也称为猴子修补.
def MyMethod(self):
return self + self
MyClass.MyMethod = MyMethod
del(MyMethod)#clean up namespace
Run Code Online (Sandbox Code Playgroud)
我不是100%确定你可以在像str这样的特殊类上执行此操作,但它对于用户定义的类很好.
更新
你在评论中证实我怀疑这对于像str这样的内置是不可能的.在这种情况下,我认为这类的C#扩展方法没有类似的东西.
最后,在C#和Python中,这些方法的便利性带来了相关的风险.使用这些技术可以使代码更难以理解和维护.
mur*_*d99 10
您可以执行您所要求的操作,如下所示:
def extension_method(self):
#do stuff
class.extension_method = extension_method
Run Code Online (Sandbox Code Playgroud)
我会在这里使用适配器模式。所以,假设我们有一个Person类,并且在一个特定的地方我们想添加一些与健康相关的方法。
from dataclasses import dataclass
@dataclass
class Person:
name: str
height: float # in meters
mass: float # in kg
class PersonMedicalAdapter:
person: Person
def __init__(self, person: Person):
self.person = person
def __getattr__(self, item):
return getattr(self.person, item)
def get_body_mass_index(self) -> float:
return self.person.mass / self.person.height ** 2
if __name__ == '__main__':
person = Person('John', height=1.7, mass=76)
person_adapter = PersonMedicalAdapter(person)
print(person_adapter.name) # Call to Person object field
print(person_adapter.get_body_mass_index()) # Call to wrapper object method
Run Code Online (Sandbox Code Playgroud)
我认为它是一个易于阅读但灵活的 Pythonic 解决方案。
您可以使用以下上下文管理器很好地实现此目的,该上下文管理器将方法添加到上下文块内的类或对象中,然后将其删除:
class extension_method:
def __init__(self, obj, method):
method_name = method.__name__
setattr(obj, method_name, method)
self.obj = obj
self.method_name = method_name
def __enter__(self):
return self.obj
def __exit__(self, type, value, traceback):
# remove this if you want to keep the extension method after context exit
delattr(self.obj, self.method_name)
Run Code Online (Sandbox Code Playgroud)
用法如下:
class C:
pass
def get_class_name(self):
return self.__class__.__name__
with extension_method(C, get_class_name):
assert hasattr(C, 'get_class_name') # the method is added to C
c = C()
print(c.get_class_name()) # prints 'C'
assert not hasattr(C, 'get_class_name') # the method is gone from C
Run Code Online (Sandbox Code Playgroud)
Sha*_*kan -14
一周后,我得到了一个最接近我所寻求的解决方案。该解决方案包括使用getattr和__getattr__。这是一个例子,供有兴趣的人参考。
class myClass:
def __init__(self): pass
def __getattr__(self, attr):
try:
methodToCall = getattr(myClass, attr)
return methodToCall(myClass(), self)
except:
pass
def firstChild(self, node):
# bla bla bla
def lastChild(self, node):
# bla bla bla
x = myClass()
div = x.getMYDiv()
y = div.firstChild.lastChild
Run Code Online (Sandbox Code Playgroud)
我还没有测试这个例子,我只是为了给可能感兴趣的人提供一个想法。希望有帮助。
| 归档时间: |
|
| 查看次数: |
11390 次 |
| 最近记录: |