假设我有两个类:
1.名为Swimmer
的类
1.名为Person
的类
对于我的特定应用程序,我们可以***NOT***让Swimmer
从Person
继承,尽管我们需要类似继承的东西。
代替类继承,每个Swimmer
将具有Person
类的示例作为成员变量。
class Swimmer:
def __init__(self, person):
self._person = person
def __getattr__(self, attrname:str):
try:
attr = getattr(self._person)
return attr
except AttributeError:
raise AttributeError
Person
类具有以下类方法:
kneel()
crawl()
walk()
lean_over()
- x1米11米1x
Swimmer
类具有与Person
类相同的所有方法,外加一些附加方法:
run()
swim()
dive()
throw_ball()
对于跪、爬、走和躺,Swimmer
应该是Person
类的透明 Package 器
我想写这样的东西:
swimmer_instance = SwimmerClass(person_instance)
我写了一个__getattr__()
方法。
但是,我遇到了许多头痛的__getattr__()
。
首先,每当我输入Swimmer
属性的名称时,我的计算机就会在Person
类的示例中搜索该属性。通常,修复这样的拼写错误很容易。但是,使用__getattr__()
方法,跟踪问题变得很困难。
我怎样才能避免这个问题?
也许一个选择是创建Swimmer
类的一个子类,在这个子类中有一个方法,这个方法的名字是拼写错误的__getattr__
,但是,我对这个想法不是很确定;请告诉我。
class _Swimmer:
def __init__(self, person):
self._person = person
def run(self):
# SHOULD NOT LOOK FOR `oops` inside of self._person!
self.oops # there is no attribute named `oops`
return "I ran"
def swim(self):
# SHOULD NOT LOOK FOR `oops` inside of self._person!
self.oops
return "I swam"
def dive(self):
# SHOULD NOT LOOK FOR `oops` inside of self._person!
self.oops
return "I dove"
def _getattrimp(self, attrname:str):
# MISSPELLING OF `__getattr__`
try:
attr = getattr(self._person)
return attr
except AttributeError:
raise AttributeError
class Swimmer(_Swimmer):
def __getattr__(self, attrname:str):
attr = self._getattrimp(attrname)
return attr
真的,对我来说,重要的是我们***不要***查看self._person
内部的任何内容,除了以下内容:
Kneel()
Crawl()
- x1米30英寸1x
Lean()
LayDown()
解必须比Swimmers
和Persons
更一般。
我们如何编写一个函数,它接受任何类作为输入,并弹出一个与输入类同名的方法的类?
我们可以通过写入person_attributes = dir(Person)
来获得Person
属性的列表。
动态创建Swimmer
的子类并将Person
作为输入是否合适?
class Person:
def kneel(self, *args, **kwargs):
return "I KNEELED"
def crawl(self, *args, **kwargs):
return "I crawled"
def walk(self, *args, **kwargs):
return "I WALKED"
def lean_over(self, *args, **kwargs):
return "I leaned over"
################################################################
import functools
class TransparentMethod:
def __init__(self, mthd):
self._mthd = mthd
@classmethod
def make_transparent_method(cls, old_method):
new_method = cls(old_method)
new_method = functools.wraps(old_method)
return new_method
def __call__(self, *args, **kwargs):
ret_val = self._mthd(*args, **kwargs)
return ret_val
###############################################################
attributes = dict.fromkeys(dir(Person))
for attr_name in attributes.keys():
old_attr = getattr(Person, attr_name)
new_attr = TransparentMethod.make_transparent_method(old_attr)
name = "_Swimmer"
bases = (object, )
_Swimmer = type(name, bases, attributes)
class Swimmer(_Swimmer):
pass
1条答案
按热度按时间avwztpqn1#
如果我没理解错的话,您需要一个将两个类合并为一个类的函数。
我做这件事的方法是创建一个空容器类,然后循环遍历传递给函数的每个类,使用
setattr
设置容器类的新属性。我不得不将__class__
和__dict__
属性列入黑名单,因为Python不允许更改这些属性。注意,这个函数将覆盖以前添加的方法,比如__init__()
方法。所以最后用构造函数传递类。我还添加了一个name
可选参数来设置类的__name__
属性,以便于调试。我在下面的
combineClasses
函数中实现了这一点。我还提供了一个例子。在这个例子中,我创建了一个基本的Person
类和一个_Swimmer
类。我在这两个类上调用了combineClasses
,并将结果类存储为Swimmer
,因此它可以很好地作为一个 Package 类调用。