因此,我正在为一款名为《战车世界》的游戏编写mod。我想使用的一件事是“ overrideMethod”,因为我认为这使我的代码看起来更简洁,更易于阅读。我从另一个Mod中使用一个,但是它被编写为使用方法中未定义的一些键。
我对编程有点陌生,所以我不知道该怎么做。
没有overrideMethod的代码示例:
if carEnabled == True:
old_as_rowsCountS = TankCarouselMeta.as_rowCountS
tankrows = carRows
def new_as_rowCountS(self, value):
old_as_rowsCountS(self, value)
if self._isDAAPIInited():
return self.flashObject.as_rowCount(tankrows)
TankCarouselMeta.as_rowCountS = new_as_rowCountS
print '[IVM] Tank Carousels Loaded with ' + str(carRows) + ' rows'
else:
print '[IVM] Tank Carousels Not Enabled'
pass
并使用overrideMethod:
@overrideMethod(TankCarouselMeta, 'as_rowCountS')
def ivmCarouselS(self, value):
if not carEnabled:
print '[IVM] Carousels Not Enabled'
return
# return self.flashObject.as_rowCount(value) if self._isDAAPIInited() else None
if self._isDAAPIInited():
print '[IVM] Carousels Enabled with %s Rows' % (carRows)
return self.flashObject.as_rowCount(carRows)
else:
None
这两个都使用from gui.Scaleform.daapi.view.meta.TankCarouselMeta import TankCarouselMeta
导入
这两个代码块当然会做同样的事情。他们所做的是更改as_rowCountS方法,以便用户可以输入所需的任何数字,只要该数字是整数即可。他们的游戏出于某种原因不允许这样做,并且最多只能将其限制为2行。此修改将允许任何数字(尽管12以上的值对于1080p来说太多了。)
有问题的overrideMethod:
import inspect
import sys
from functools import partial, update_wrapper
#@overrideMethod
def overrideMethod(obj, prop, getter=None, setter=None, deleter=None):
"""
:param obj: object, which attribute needs overriding
:param prop: attribute name (can be not mangled), attribute must be callable
:param getter: fget function or None
:param setter: fset function or None
:param deleter: fdel function or None
:return function: unmodified getter or, if getter is None and src is not property, decorator"""
if inspect.isclass(obj) and prop.startswith('__') and prop not in dir(obj) + dir(type(obj)):
prop = obj.__name__ + prop
if not prop.startswith('_'):
prop = '_' + prop
src = getattr(obj, prop)
if type(src) is property and (getter or setter or deleter):
props = []
for func, fType in ((getter, 'fget'), (setter, 'fset'), (deleter, 'fdel')):
assert func is None or callable(func), fType + ' is not callable!'
props.append(partial(func, getattr(src, fType)) if func else getattr(src, fType))
setattr(obj, prop, property(*props))
return getter
elif getter:
getter_orig = getter
assert callable(src), 'Source property is not callable!'
assert callable(getter_orig), 'Handler is not callable!'
while isinstance(getter, partial):
getter = getter.func
def getter_new(*a, **k): # noinspection PyUnusedLocal
info = None
try:
return getter_orig(src, *a, **k)
except Exception: # Code to remove this wrapper from traceback
info = sys.exc_info()
new_tb = info[2].tb_next # https://stackoverflow.com/q/44813333
if new_tb is None: # exception occurs inside this wrapper, not inside of getter_orig
new_tb = _generate_new_tb(getter.func_code)
raise info[0], info[1], new_tb
finally:
del info
try:
update_wrapper(getter_new, getter)
except AttributeError:
pass
if inspect.isclass(obj):
if inspect.isfunction(src):
getter_new = staticmethod(getter_new)
elif getattr(src, '__self__', None) is not None:
getter_new = classmethod(getter_new)
setattr(obj, prop, getter_new)
return getter_orig
else:
return partial(overrideMethod, obj, prop)
因此,一些问题: 有更好的方法吗? 我使用正确吗? 在修改本身上我有什么需要改进的地方(请忽略非重写方法之一中的菜鸟错误)?
感谢所有提供帮助的人:)