كيفية إنشاء وظائف مستوى الوحدة النمطية ديناميكيًا من الأساليب في الفصل
-
01-10-2019 - |
سؤال
أحاول إنشاء وظائف مستوى الوحدة النمطية من الأساليب في الفصل. لذلك لكل طريقة في الفصل ، أريد إنشاء وظيفة بنفس الاسم الذي ينشئ مثيلًا للفصل ثم يستدعي الطريقة.
السبب في أنني أرغب في القيام بذلك هو حتى أتمكن من اتباع نهج موجه نحو الكائن لإنشاء ملفات الأقمشة. نظرًا لأن النسيج سوف يستدعي وظائف مستوى الوحدة النمطية ولكن ليس طرق الفصل ، فهذا هو عملي.
لقد استخدمت الروابط التالية لتبدأ
- كيف أحصل على قائمة بالطرق في فئة بيثون؟
- إضافة وظائف ديناميكي إلى وحدة بيثون
- كيف يمكنني استدعاء setattr () على الوحدة الحالية؟
- http://effbot.org/zone/python-getattr.htm
- استدعاء وظيفة وحدة من سلسلة تحمل اسم الوظيفة في بيثون
- كيفية تعديل مساحة الاسم المحلية في بيثون
وقد توصلت إلى الرمز التالي
import inspect
import sys
import types
class TestClass(object):
def __init__(self):
pass
def method1(self, arg1):
print 'method 1 %s' % arg1
def method2(self):
print 'method 2'
def fabric_class_to_function_magic(module_name):
# get the module as an object
print module_name
module_obj = sys.modules[module_name]
print dir(module_obj)
# Iterate over the methods of the class and dynamically create a function
# for each method that calls the method and add it to the current module
for method in inspect.getmembers(TestClass, predicate=inspect.ismethod):
print
print method
method_name, method_obj = method
# create a new template function which calls the method
def newfunc_template(*args, **kwargs):
tc = TestClass()
func = getattr(tc, method_name)
return func(*args, **kwargs)
# create the actual function
print 'code: ', newfunc_template.func_code
print 'method_name: ', method_name
newfunc = types.FunctionType(newfunc_template.func_code,
{'TestClass': TestClass,
'getattr': getattr,
'method_name': method_name,
},
name=method_name,
argdefs=newfunc_template.func_defaults,
closure=newfunc_template.func_closure,
)
# add the new function to the current module
setattr(module_obj, method_name, newfunc)
# test the dynamically created module level function
thismodule = sys.modules[__name__]
print dir(thismodule)
fabric_class_to_function_magic(__name__)
print dir(thismodule)
method1('arg1')
method2()
وأحصل على الخطأ التالي
['TestClass', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fabric_class_to_function_magic', 'inspect', 'sys', 'thismodule', 'types']
__main__
['TestClass', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fabric_class_to_function_magic', 'inspect', 'sys', 'thismodule', 'types']
('__init__', <unbound method TestClass.__init__>)
code: <code object newfunc_template at 0x7f8800a28d50, file "test.py", line 85>
method_name: __init__
('method1', <unbound method TestClass.method1>)
code: <code object newfunc_template at 0x7f8800a28d50, file "test.py", line 85>
method_name: method1
('method2', <unbound method TestClass.method2>)
code: <code object newfunc_template at 0x7f8800a28d50, file "test.py", line 85>
method_name: method2
['TestClass', '__builtins__', '__doc__', '__file__', '__init__', '__name__', '__package__', 'fabric_class_to_function_magic', 'inspect', 'method1', 'method2', 'sys', 'thismodule', 'types']
Traceback (most recent call last):
File "test.py", line 111, in <module>
method1('arg1')
File "test.py", line 88, in newfunc_template
return func(*args, **kwargs)
TypeError: method2() takes exactly 1 argument (2 given)
يبدو أنه يعيد استخدام الإشارة إلى الوظيفة؟ أيه أفكار؟
تحديث: هنا هو رمز العمل مع إصلاح Ned Batchelder
def fabric_class_to_function_magic(module_name):
# get the module as an object
module_obj = sys.modules[module_name]
# Iterate over the methods of the class and dynamically create a function
# for each method that calls the method and add it to the current module
for method in inspect.getmembers(TestClass, predicate=inspect.ismethod):
method_name, method_obj = method
# get the bound method
tc = TestClass()
func = getattr(tc, method_name)
# add the function to the current module
setattr(module_obj, method_name, func)
تحديث 2: هنا هو منشور مدونتي حول هذا الموضوع: http://www.saltycrane.com/blog/2010/09/Class-
المحلول
أنت مفرط في التفكير في الحل. تغيير نهاية fabric_class_to_function_magic
ليكون هذا:
tc = TestClass()
func = getattr(tc, method_name)
# add the new function to the current module
setattr(module_obj, method_name, func)
وهو يعمل بشكل جيد. لا حاجة لإنشاء كائن وظيفة جديد ، لديك بالفعل واحدة تم إرجاعها بواسطة GetAttr على كائنك. الطريقة المربوطة التي تم إرجاعها بواسطة GetAttr هي شيء قابل للاستدعاء. ما عليك سوى تعيينه إلى سمة الوحدة النمطية ، وأنت على ما يرام.
نصائح أخرى
في الواقع ، يكون رمزك صحيحًا ، ولكن عندما يتم تنفيذ Func (*args ، ** kwargs) ، فإن Args سوف تمر Tuple فارغ مثل () ولا توجد معلمات في طريقتك 2 ، لذلك يثير مثل هذا الاستثناء ،
سيكون الحل السريع تجاه مشكلتك ، مثل
class TestClass(object):
def __init__(self):
pass
def method1(self, arg1):
print 'method 1 %s' % arg1
def method2(self, *args, **kw):
print 'method 2'