2015-06-25 5 views
1

Я хочу, чтобы извлечь - имя «текущего» Methode - имя класса текущего объекта/экземпляр - имя класса следующего базового класса этого объекта/напримерПолучить имя текущего метода, имя класса текущего экземпляра, имя класса следующего вспомогательного экземпляра в многоразовом режиме с помощью Python3?

Проблемы в приведенный ниже пример заключается в том, что имя метода не совсем то, что я хочу. Но мне нужно сделать этот код многократным для многих классов. Я не хочу умножать этот код для каждого класса, в котором я нуждаюсь.

#!/usr/bin/env python3 
# -*- coding: utf-8 -*- 

import sys, inspect 

def notimpl_str(obj): 
    classname = obj.__class__.__name__ 

    methode = sys._getframe().f_code.co_name 

    hi = inspect.getmro(obj.__class__) 
    nistr = 'In {}.{}()\nLook in {}.{}()' \ 
     .format(classname, 
       methode, 
       hi[1].__name__, 
       methode) 

    return nistr 


class Foo: 
    def test(self): 
     print(notimpl_str(self)) 

class Xoo(Foo): 
    def __init__(self): 
     self.test() 

Xoo() 

фон моего вопроса: Я хочу осуществить общий не реализованная-сообщения об ошибке, если кто-то назовет Xoo().test(). Сообщение может быть Please implement Xoo.test(). See the documentation of Foo.test() for more details.

ответ

2

Это далеко от совершенства, но немного ближе к «родовому». ;)

#!/usr/bin/env python3 
# -*- coding: utf-8 -*- 

import sys, inspect 

def create_niestr(obj, 
        abstract_class, 
        methode): 
    classname = obj.__class__.__name__ 
    hi = inspect.getmro(obj.__class__) 
    this_method = getattr(obj, methode) 
    base_method = getattr(abstract_class, methode) 

    if classname is not abstract_class.__name__ and this_method.__func__ is base_method: 
     nistr = 'Please implement {}.{}(). See the documentation of {}.{}() for more details.' \ 
       .format(classname, methode, hi[1].__name__, methode) 
    else: 
     nistr = 'Normal execution.' 

    return nistr 


class Foo: 
    def test(self): 
     nistr = create_niestr(self, 
           Foo, 
           sys._getframe().f_code.co_name) 
     print(nistr) 


class Xoo(Foo): 
    pass 

class Zoo(Foo): 
    def test(self): 
     super(self.__class__, self).test() 

Foo().test() 
Xoo().test() 
Zoo().test() 
+1

Рад, что вы смогли решить вашу проблему. :) – CrakC

1

Я думаю, что это то, что вы ищете. Я добавил дополнительный параметр 'Inheritance hierarchy'.

import sys 
import inspect 

class Foo(object): 
    def __init__(self): 
     flag = 0 
     print("Subclasses:", end=" ") 
     for subclass in self.__class__.__subclasses__(): #prints the subclasses 
      print(subclass.__name__, end=" ") 
      flag = 1 
     if flag == 0: 
      print(None) 
     else: 
      print() 
     print("Class name: ", self.__class__.__name__) #prints the class name 
     print("Method name: ", sys._getframe().f_code.co_name) #prints the method name 
     a = inspect.getmro(self.__class__) 
     flag = 0 
     print("Inheritance Hierarchy:", end=" ") 
     for i in range(len(a)): #prints the inheritance hierarchy 
      if not i == 0: 
       print(a[(len(a)-1)-i].__name__, end=" ") 
       flag = 1 
     if flag == 0: 
      print(None) 
     else: 
      print("\n") 

class Xoo(Foo): 
    def __init__(self): 
     flag = 0 
     print("Subclasses:", end=" ") 
     for subclass in self.__class__.__subclasses__(): #prints the subclasses 
      print(subclass.__name__, end=" ") 
      flag = 1 
     if flag == 0: 
      print(None) 
     else: 
      print() 
     print("Class name: ", self.__class__.__name__) #prints the class name 
     print("Method name: ", sys._getframe().f_code.co_name) #prints the method name 
     a = inspect.getmro(self.__class__) 
     flag = 0 
     print("Inheritance Hierarchy:", end=" ") 
     for i in range(len(a)): #prints the inheritance hierarchy 
      if not i == 0: 
       print(a[(len(a)-1)-i].__name__, end=" ") 
       flag = 1 
     if flag == 0: 
      print(None) 
     else: 
      print("\n") 

class Zoo(Xoo): 
    def __init__(self): 
     flag = 0 
     print("Subclasses:", end=" ") 
     for subclass in self.__class__.__subclasses__(): #prints the subclasses 
      print(subclass.__name__, end=" ") 
      flag = 1 
     if flag == 0: 
      print(None) 
     else: 
      print() 
     print("Class name: ", self.__class__.__name__) #prints the class name 
     print("Method name: ", sys._getframe().f_code.co_name) #prints the method name 
     a = inspect.getmro(self.__class__) 
     flag = 0 
     print("Inheritance Hierarchy:", end=" ") 
     for i in range(len(a)): #prints the inheritance hierarchy 
      if not i == 0: 
       print(a[(len(a)-1)-i].__name__, end=" ") 
       flag = 1 
     if flag == 0: 
      print(None) 
     else: 
      pass 

Foo() 
Xoo() 
Zoo() 

Запуск выше код, вы получаете следующие OUTPUT:

Subclasses: Xoo 
Class name: Foo 
Method name: __init__ 
Inheritance Hierarchy: Foo 

Subclasses: Zoo 
Class name: Xoo 
Method name: __init__ 
Inheritance Hierarchy: Foo Xoo 

Subclasses: None 
Class name: Zoo 
Method name: __init__ 
Inheritance Hierarchy: Foo Xoo Zoo 
+0

Возможно, это может помочь. Я проверю позже. Но есть некоторые проблемы понимания. Первый экземпляр 'Foo()' не имеет подкласса, а возвращает 'Xoo' в качестве подкласса. Но экземпляр никогда не получал этого подкласса. Это просто 'Foo()'. Может быть, я должен более точно спросить «класс суб-экземпляра». Увидеть разницу? – buhtz

+1

хорошо, кажется, что вы смешиваете вещи. 'Foo' действительно имеет подкласс под названием' Xoo', как описано вашим вопросом и реализован мной. Кроме того, вы не дали понять, хотите ли вы, чтобы метод печатал все производные классы текущего класса или базового класса текущего класса? В любом случае мой код был бы уместным, так как вы можете увидеть, что он печатает оба ** подкласса ** и ** иерархию наследования ** данного класса. Однако, если это не то, что вы хотите, вы можете рассмотреть вопрос об изменении вопроса и добавить к нему дополнительные сведения. – CrakC

+0

Переделать тему. Первый экземпляр Foo() не имеет ничего общего с Xoo или Zoo и ничего не знает об этом. btw: Ваш код работает с Python3? – buhtz

1

Проверьте это!

#!/usr/bin/env python3 
# -*- coding: utf-8 -*- 

import sys, inspect 

class Foo: 
    def test(self): 
     classname = self.__class__.__name__ 
     methode = sys._getframe().f_code.co_name 
     hi = inspect.getmro(self.__class__) 
     this_method = getattr(self, 'test') 
     base_method = getattr(Foo, 'test') #here 'Foo' is the base class and so this value has to be hard-coded for every base class inside which you paste this code 
     if classname is not "Foo" and this_method.__func__ is base_method: 
      nistr = 'Please implement {}.{}(). See the documentation of {}.{}() for more details.'\ 
      .format(classname, methode, hi[1].__name__, methode) 
      print(nistr) 
     else: 
      print("Normal execution.") #put the actual code for the 'test' method here 

class Xoo(Foo): 
    pass 

class Zoo(Foo): 
    def test(self): 
     super(self.__class__, self).test() 

Foo().test() #test has been defined so normal execution 
Xoo().test() #test has not been defined so a message is shown 
Zoo().test() #test has been defined, even if it is just for calling the base class's 'test' method, it is still a valid definition so normal execution 

output-

Normal execution. 
Please implement Xoo.test(). See the documentation of Foo.test() for more details. 
Normal execution. 

О реализации унифицированного метода, как вы показали в этом вопросе, а, я бы сказал, что создаст много путаницы и не может быть даже возможно, как значение self не может содержать вызывающий объект, а также вызываемый объект. Кроме того, если ваш вызов еще один метод для проверки этого, то sys._getframe().f_code.co_name больше не будет возвращать имя исходного метода, что вам нужно. Таким образом, лучший способ - добавить этот кусок кода в каждый базовый класс.

+0

Очень приятно. И я понимаю проблемы об общем методе. Разве нет что-то вроде заполнителя в Python: как #define в C++ я мог бы использовать здесь? Интересно, почему Python не справляется с тем, что могут существовать «абстрактные» классы. – buhtz

+0

@buhtz python действительно поддерживает «абстрактные классы». Проверьте это: https://docs.python.org/3/library/abc.html Также у вас есть поддержка «глобальных переменных» (http://stackoverflow.com/questions/423379/using-global-variables- in-a-function-other-than-the-one-that-created-them), которые могут помочь вам легко получить доступ к различным параметрам, необходимым внутри общей функции. Об определении 'констант', вот трюк ** ** - http://code.activestate.com/recipes/65207-constants-in-python/?in=user-97991 – CrakC

Смежные вопросы