2015-09-06 2 views
2

Скажут, у меня есть набор классов, как это:Python: Ссылки между подклассами

class User(object): 

    def __init__(self, profile): 
     # ... 
     pass 

    @classmethod 
    def create_user(cls): 
     profile = Profile() 
     user = cls(profile) 

class Profile(object): 
    pass 

class SpecialUser(User): 
    pass 

class SpecialProfile(Profile): 
    pass 

Всякий раз, когда я хочу создать подкласс User или Profile, мне нужно сортировать подкласс все из них, потому что с кодом выше, если я сделаю SpecialUser.create_user(), это будет особый пользователь, но с обычным профилем.

Простейшее обходное решение заключается в том, чтобы сделать встроенную фабричную функцию внутри User, что создает соответствующий Profile. Однако это может быть утомительным. Что делать, если у пользователя был профиль и как 10 других классов? Должен ли я переопределить заводскую функцию для каждого из них? Что делать, если другие классы также ссылаются друг на друга? Все ли эти классы нуждаются в фабричных функциях?

Я думал о делать что-то вроде этого:

class UserClasses(object): 

    class User(object): 

     def __init__(self, profile): 
      # ... 
      pass 

     @classmethod 
     def create_user(cls): 
      profile = cls.__parent__.Profile() 
      user = cls(profile) 

    class Profile(object): 
     pass 

class SpecialUserClasses(UserClasses): 

    class Profile(UserClasses.Profile): 
     pass 

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

Как я могу получить classmethod-like функциональность, но для групп связанных классов?

+1

Вам действительно нужно иметь возможность обрабатывать «10 других классов, которые также ссылаются друг на друга»? Если между всеми этими классами может быть произвольная сеть ссылок, я не вижу, как вы могли бы справиться с ней, не запутывая и не трудившись. – BrenBarn

+0

Это звучит как [ACL] (http://www.limscoder.com/2009/11/role-based-security-with-python.html). Это то, что вы ищете? – dawg

+0

@BrenBarn, в моем конкретном случае эти классы будут [SQLAlchemy] (http://www.sqlalchemy.org/) моделями с отношениями друг с другом (и фактически абстрактными в этом), поэтому им нужно будет иметь такую ​​информацию, как «У пользователя есть профиль», «Комментарий у пользователя» и т. Д. – awesome

ответ

2

Вам не обязательно использовать переопределяемую функцию. Вы могли бы просто иметь Overridable атрибут:

class User(object): 

    profile_class = Profile 

    def __init__(self, profile): 
     # ... 
     pass 

    @classmethod 
    def create_user(cls): 
     profile = cls.profile_class() 
     user = cls(profile) 

Тогда подклассы могут только определить свой собственный profile_class атрибут, и он будет работать. Для этого, однако, любой класс пользователя должен быть определен после соответствующего класса профиля (поскольку класс пользователя ссылается на класс профиля в кубе класса). Это ограничивает сложность перекрестной ссылки, которую вы можете иметь. Однако на самом деле сложная система взаимосвязанных классов часто сбивает с толку и хрупка.

+0

Будет ли удобный способ поместить profile_class, other_class, someother_class в «заводский класс» и иметь ли каждый класс ссылку только на этот класс? Я думаю, используя декораторы, чтобы установить каждый класс как атрибут на нем. – awesome

+0

@awesome: Извините, я не понимаю, что вы имеете в виду. Что такое «просто этот класс»? – BrenBarn