2017-08-31 26 views
0

考慮下面的情況下,Python - 如何將實例變量值傳遞給描述符參數?

ITEMLIST類:

# filename: item_list.py 

# locators dictionary is intentionally placed outside `ItemList` class 
locators = { 
    'item_id': 'css=tr:nth-of-type({item_num}) .id', 
    'item_title': 'css=tr:nth-of-type({item_num}) .alert-rules', 
    # other properties 
} 

class ItemList(Item): 
    # --- these are data descriptors --- 
    # getting item_id value based on its item_num 
    item_id = TextReadOnly(locators['item_id'].format(item_num=self.item_num)) 

    # getting item_title value based on its item_num 
    item_title = TextReadOnly(locators['item_title'].format(item_num=self.item_num)) 


    def __init__(self, context, item_num=0): 
     # self.item_num can't be passed to locators 
     self.item_num = item_num 

     super(ItemList, self).__init__(
      context 
     ) 

在這種情況下,我想通過self.item_numitem_num內定位符詞典中ItemList類。

原因是我想要item_iditem_title中的每一個都指特定的item_num

我卡在這一部分:

item_id = TextReadOnly(locators['item_id'].format(item_num=self.item_num)) 
item_title = TextReadOnly(locators['item_title'].format(item_num=self.item_num)) 

self.item_num值不能被傳遞到定位器時,實例已經作出。

實現:

# filename: test.py 

# print item_id values from item_num=1 
item_1 = ItemList(context, 1) 
print (‘Item_id_1: ’ + item_1.id) 

# print item_id values from item_num=2 
item_2 = ItemList(context, 2) 
print (‘Item_id_2: ’ + item_2.id) 

#^no result produced from item_1.id and item_2.id because self.item_num value can't be passed to locators 

是否有可能從更新實例變量數據的描述符?

如何將實例變量值傳遞給數據描述符參數?


附加信息:

席力圖召item_iditem_title作爲實例屬性,但沒有運氣。我注意到,數據描述符不能從這個帖子實例屬性:Data descriptor should be a class attribute

項目類:

# filename: item.py 

import abc 


class Item(Page): 
    __metaclass__ = abc.ABCMeta 

    def __init__(self, context): 
     self.__context = context 
     super(Item, self).__init__(
      self.__context.browser 
     ) 

描述:

# filename: text_read_only.py 

class TextReadOnly(object): 
    def __init__(self, locator): 
     self.__locator = locator 

    def __get__(self, instance, owner=None): 
     try: 
      e = instance.find_element_by_locator(self.__locator) 
     except AttributeError: 
      e = instance.browser.find_element_by_locator(self.__locator) 

     return e.text 

    def __set__(self, instance, value): 
     pass 
+1

我認爲你做錯了 - 類屬性不能取決於實例屬性,因爲類是首先初始化的。如果你想讓'item_id'和'item_title'每個實例有所不同,爲什麼要把它們放在class屬性中呢? – domoarrigato

+0

Hello @domoarrigato:我將'item_id'和'item_title'設置爲類屬性,因爲我想使用描述符** TextReadOnly **。我注意到[這篇文章](https://stackoverflow.com/questions/12599972/descriptors-as-instance-attributes-in-python)數據描述符應該是一個類屬性。是否有另一種方法來實現它? –

+1

如果你想保留它們作爲類的屬性,你可以嘗試使它們成爲「受保護的類的屬性」,參見[this] [1]的問題來看看如何。 在你的具體情況下,我認爲這是矯枉過正,'item_id'和'item_title'看起來更像實例描述符而不是數據描述符,所以我將它們作爲實例屬性。 [1]:https://stackoverflow.com/questions/5189699/how-to-make-a-class-property – Hrabal

回答

0

我發現this article並想出瞭解決方案添加描述符到一個對象。

低於該解決方案爲我工作:

  1. 添加__getattribute____setattr__項目類

    # filename: item.py 
    
    import abc 
    
    
    class Item(Page): 
        __metaclass__ = abc.ABCMeta 
    
        def __init__(self, context): 
         self.__context = context 
         super(Item, self).__init__(
          self.__context.browser 
         ) 
    
        def __getattribute__(self, name): 
         value = object.__getattribute__(self, name) 
         if hasattr(value, '__get__'): 
          value = value.__get__(self, self.__class__) 
         return value 
    
        def __setattr__(self, name, value): 
         try: 
          obj = object.__getattribute__(self, name) 
         except AttributeError: 
          pass 
         else: 
          if hasattr(obj, '__set__'): 
           return obj.__set__(self, value) 
         return object.__setattr__(self, name, value) 
    
  2. 移動類屬性爲實例屬性中ITEMLIST構造

    # filename: item_list.py 
    
    # locators dictionary is intentionally placed outside `ItemList` class 
    locators = { 
        'item_id': 'css=tr:nth-of-type({item_num}) .id', 
        'item_title': 'css=tr:nth-of-type({item_num}) .alert-rules', 
        # other properties 
    } 
    
    
    class ItemList(Item): 
        def __init__(self, context, item_num=0): 
         self.item_num = item_num 
         # self.item_num is able to be passed to locators 
         self.item_id = TextReadOnly(locators['item_id'].format(item_num=self.item_num)) 
         self.item_title = TextReadOnly(locators['item_title'].format(item_num=self.item_num)) 
    
         super(ItemList, self).__init__(
          context 
         ) 
    
相關問題