Python: как динамически назначить имя функции в классе
У меня есть вопрос о том, как динамически присваивать имя функции в классе.
Например:
If a class wants to be used for "for...in" loop, similar to a list
or a tuple, you must implement an __iter__ () method
python2.x will use __iter__() and next(),
python3.x need to use __iter__() and __next__()
Код:
Пример-получить числа Фибоначчи в пределах 10
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self):
return self
if sys.version_info[0] == 2:
iter_n = 'next' #if python version is 2.x
else:
iter_n = '__next__' #if python version is 3.x
print('iter_n value is ', iter_n)
#for py2 I want to replace "iter_n" to "next" dynamically
#for py3 I want to replace "iter_n" to "__next__" dynamically
def iter_n(self):
self.a, self.b = self.b, self.a + self.b
if self.a > 10:
raise StopIteration();
return self.a
Тест:
for i in Fib():
print(i)
Ожидаемый результат должен быть:
('iter_n value is ', 'next')
1
1
2
3
5
8
Фактический Результат:
('iter_n value is ', 'next')
Traceback (most recent call last):
......
TypeError: iter() returned non-iterator of type 'Fib'
Код сможет получить правильные результаты
- для python 2, Если я заменю
def iter_n(self)наdef next(self)
- для python 3, Если я заменю
def iter_n(self)наdef __next__(self)
Вопрос:
Как я должен поместить next или __next__ в iter_n динамически?
3 ответов:
Я не думаю, что есть необходимость создавать этот метод динамически. Просто реализуйте оба; яснее и проще. И ваш код будет совместим с Python 2/3 без необходимости использования оператора if.
class Fib(object): def __init__(self): self.a, self.b = 0, 1 def __iter__(self): return self def iter_n(self): self.a, self.b = self.b, self.a + self.b if self.a > 10: raise StopIteration(); return self.a def next(self): return self.iter_n() def __next__(self): return self.iter_n() if __name__ == '__main__': for i in Fib(): print(i)
Согласился, что просто реализовать оба варианта, вероятно, лучше, но что-то вроде этого, кажется, делает то, что вы намереваетесь:
def iter_n(self): self.a, self.b = self.b, self.a + self.b if self.a > 10: raise StopIteration(); return self.a if sys.version_info[0] == 2: next = iter_n else: __next__ = iter_n del iter_nВышеизложенное удаляет исходный
iter_n, Как только он присваивается соответствующему атрибуту. Вероятно, если вы проходите через это усилие, вы бы тоже хотели сделать эту очистку.
В python есть способ вызвать функцию, метод, получить любой элемент с помощью getattr (from, 'name of attribute to call').
Ниже приведен пример этого:
class A(): def s(self): print "s fun" def d(self): print "a fun" def run(self): print "in run" def main(): print "in main" classA = A() func_list = ['s','d','run'] for i in func_list: func = getattr(classA,i) func() main()Попробуйте использовать это для динамического вызова функции.
Comments