2013-11-08 3 views
2

Я уверен, что это будет отмечено как дубликат, но я действительно не понимаю, что я ищу. Я проверил документацию на python в дескрипторах, но я уже «две недели программировал» на Python, и я действительно не знаю, что я ищу!Дескрипторы Python __get__ и __set__

Это то, что я получил:

>>> class Blub(object): 
...  def __init__(self, value): 
...    print('Blub is ' + value) 
...    self.value = value 
...  def __get__(self): 
...    print('Blub gets ' + self.value) 
...    return self.value 
...  def __set__(self, value): 
...    print('Blub becomes ' + value) 
...    self.value = value 
... 
>>> class Quish(object): 
...  def __init__(self, value): 
...    self.blub = Blub(value) 
...  def __get__(self): 
...    return self.blub 
...  def __set__(self, value): 
...    self.blub = Blub(value) 
... 

Ниже то, что я хочу, чтобы это произошло, и не знаю, как это сделать:

>>> a = Quish('One') 
Blub is One 
>>> a.blub 
Blub gets One 
'One' 
a.blub = 'Two' 
Blub becomes Two 

Что делать в Blub или Quish в чтобы это произошло. У меня есть очень простые классы здесь, но у меня есть гораздо более сложная версия, которая работает отлично, но только если я типа:

>>> a.blub.__get__() 

Я думал, что точка этих дескрипторов было сделать ненужным фактически написать получить() и комплект(). Как заставить его вести себя так, как хотелось бы, или Python не может этого сделать?

+1

Есть ли причина, по которой вы хотите написать свой собственный класс дескриптора для этого вместо использования 'property'? – BrenBarn

+0

@BrenBarn: Я не знал о свойствах. Я все еще пытаюсь решить, что лучше (проще) использовать в этой ситуации. Я должен задать еще один вопрос относительно моего фактического монстра noob-класса, над которым я работал, чтобы понять это. Спасибо, что указали это. Больше чтения мне нужно сделать сейчас! – Sean

+0

Свойства почти наверняка легче, чем писать собственный дескриптор. – BrenBarn

ответ

2

Обычно вы не использовали дескрипторы напрямую, но используете property, который представляет собой реализацию дескриптора простым в использовании способом. Вот как вы бы использовать:

class Quish(object): 
    def __init__(self, value): 
     self.blub = value 

    @property 
    def blub(self): 
     print('Blub gets ' + self._blub) 
     return self._blub 

    @blub.setter 
    def blub(self, value): 
     print('Blub becomes ' + value) 
     self._blub = value 

Если вы действительно хотите, чтобы написать свой собственный дескриптор, ваша проблема в том, что он должен быть установлен непосредственно на типе, а не другой атрибут экземпляра, и вы будете нуждаться чтобы иметь один дескриптор нескольких экземпляров:

class Blub(object): 
    def __get__(self, instance, owner): 
     print('Blub gets ' + instance._blub) 
     return instance._blub 

    def __set__(self, instance, value): 
     print('Blub becomes ' + value) 
     instance._blub = value 


class Quish(object): 
    blub = Blub() 

    def __init__(self, value): 
     self.blub = value 
+1

Важным моментом является то, что вы не создаете отдельный дескриптор для каждого экземпляра. Существует дескриптор * one *, хранящийся в классе, и он управляет доступом к атрибуту per-instance ('_blub') для каждого экземпляра. – BrenBarn

+0

Итак, у меня есть несколько сложный парсер, с которым я пытаюсь это сделать. Он получает файл, который получает строки, содержащие поля, один из которых является типом, а другой - путь, из которого я получаю расширение файла. В настоящее время я работаю, но мне нужно получить доступ к расширению файла, набрав «if f.line [0] .extension .__ get __() == 'rtf' и f.line [0] .type .__ get __() == 15 ... "нет никакого способа сказать" if f.line [0] .extension == 'rtf' и f.line [0] .type == 15 ... "? потому что тогда мне нужно изменить расширение и тип, который будет неаккуратно выглядеть в спешке. – Sean

+1

@Sean: Python позволяет вам переопределять подобные вещи, используя дескрипторы, не требуя явного вызова '__get__'; единственная причина, по которой он не работает для вас, заключается в том, что вы помещаете дескриптор в экземпляры 'Quish', когда им нужно быть в типе' Quish'. Посмотрите, как во втором блоке кода у меня есть 'blub = Blub()' * вне * '__init__'? Это важно; в противном случае Python не будет распознавать его как дескриптор. – icktoofay