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 динамически?

432   3  

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

    Ничего не найдено.