2015-06-08 3 views
2
class db: 

     global_ids = {} 
     global_mappings = {} 
     def __init__: 

      db_client  = sth sth #clinet to mongo db 
      db_connection = sth sth #connection to mongo db 
      db_coll  = sth sth 

Мне нужны некоторые переменные класса (global ids и global mappings), которые могут быть инициализированы только один раз для класса db и все другие экземпляры db класса могут использовать его.переменные Инициализация класса только один раз

Значение переменных класса должно быть рассчитано с использованием некоторой функции, которая смотрит в базу данных. Как я могу структурировать свой класс?

+0

Почему они являются атрибутами класса * и * 'global'? Почему бы не предоставить метод класса для их инициализации или какой-либо заводской метод динамического создания класса? – jonrsharpe

+0

у вас будут какие-то объекты (переменные), которые являются «глобальными» в вашем классе, а затем функция внутри класса, которая принимает ввод, и делает расчет –

+0

@ JohnRuddell..это, чтобы вызвать эту функцию? –

ответ

2

Вы всегда можете проверить, были ли эти значения заданы первыми; если вы не используете темы, что является просто:

class db: 
     global_ids = {} 
     global_mappings = {} 

     def __init__(self): 
      self.db_client  = sth sth #clinet to mongo db 
      self.db_connection = sth sth #connection to mongo db 
      self.db_coll  = sth sth 

      if not db.global_ids: 
       # set key-value pairs on db.global_ids 

      if not db.global_mappings: 
       # set key-value pairs on db.global_mappings 

Таким образом, вы Defer настройки того класса Атрибутов, пока первый раз при создании экземпляра класса.

Вы также можете установить те же самые значения, если определяет класс, конечно.

+0

как это будет работать, если я получаю доступ к переменным класса global_ids и global_mappings, не создавая никакой переменной класса? –

+0

@PrannoyMittal: он не будет; в этом случае вам просто нужно установить эти параметры раньше, например. вручную запускать настройку переменных. –

0

Вы можете думать об этом как о memoizedclass property.

Хотя classproperty не питон встроенной, легко реализовать:

class classproperty(object): 
    """ @[email protected] """ 
    def __init__(self, f): 
     self.f = classmethod(f) 
    def __get__(self, *a): 
     return self.f.__get__(*a)() 

Это может быть использовано как:

class A: 
    @classproperty 
    def client1(cls): 
     print("creating a client1 for %s..." % cls) 
     return 0 

print(A.client1) 
print(A.client1) 
print(A().client1) 

Output: 
creating a client1 for <class '__main__.A'>... 
0 
creating a client1 for <class '__main__.A'>... 
0 
creating a client1 for <class '__main__.A'>... 
0 

То, что осталось теперь memoizing, поэтому декорированное функция только получает вызов один раз, а будущие вызовы возвращают значение, вычисленное в первый раз. Это может быть сделано путем «инъекций» значение в A.__dict__, который вызывает будущие вызовы для доступа к нему напрямую, вместо classproperty:

class memoized_classproperty(object): 
    """ @[email protected] """ 
    def __init__(self, f): 
     self.f = classmethod(f) 
    def __get__(self, instance, owner): 
     # get the value: 
     value = self.f.__get__(instance, owner)() 
     # inject the value into class's __dict__ before returning: 
     attr = self.f.__func__.__name__ 
     setattr(owner, attr, value) 
     return value 

class A: 
    @memoized_classproperty 
    def client2(cls): 
     print("creating a client2 for %s..." % cls) 
     return 0 

print(A.client2) 
print(A.client2) 
print(A().client2) 

Output: 
creating a client2 for <class '__main__.A'>... 
0 
0 
0 
0

Я бы поставил все глобальные переменные класса в отдельный класс, который смекалку инициализирует себя, а затем создать экземпляр этого в __init__() метода класса баз данных, как показано в коде ниже:

class DBGlobals(object): 
    initialized = False 
    ids = {} 
    mappings = {} 

    def __init__(self): 
     if not self.initialized: 
      print('initializing globals') 
      self.ids = {'ans': 41}   # initialize as needed 
      self.mappings = {'v1': 'v2'} # initialize as needed 
      self.initialized = True 

class DB(object): 
    dbglobals = DBGlobals() 
    def __init__(self): 
     db_client  = sth sth #clinet to mongo db 
     db_connection = sth sth #connection to mongo db 
     db_coll  = sth sth 

Вы можете ссылаться на глобальные данные в методах класса с self.dbglobals.ids и self.dbglobals.mappings соответственно. Также было бы возможно передать аргументы конструктору класса globals, чтобы при необходимости настроить его создание.

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