Você está na página 1de 7

http://www.ibm.com/developerworks/br/library/os-pythondescriptors/index.

html

Introduo aos Descritores Python


Gerencie o acesso a atributos com descritores Python Introduo Os descritores Python foram introduzidos no Python 2.2, junto com as novas classes de estilo, mas continuam sendo muito pouco usados. Eles so uma maneira de criar atributos gerenciados. Entre suas muitas vantagens, os atributos gerenciados so usados para proteger um atributo contra alteraes ou para atualizar automaticamente os valores de um atributo dependente. Os descritores ampliam o conhecimento sobre o Python e melhoram as qualificaes de criao de cdigo. Este artigo apresenta o protocolo de descritor e demonstra como criar e usar descritores. Protocolo dos descritores O protocolo de descritor do Python simplesmente uma maneira de especificar o que acontece quando uma referncia a um atributo em um modelo feita. Ele permite que um programador gerencie o acesso a atributos de forma rpida e eficiente: set get delete Em outras linguagens de programao, os descritores so chamados de setter e getter, nos quais funes pblicas so usadas para obter e definir uma varivel privada. O Python no possui o conceito de variveis privadas, e o protocolo de descritor pode ser considerado uma maneira de obter resultado semelhante nessa linguagem. Em geral, um descritor um atributo de objeto com um comportamento de ligao, cujo acesso a atributos substitudo por mtodos no protocolo de descritor. Esses mtodos so: __get__, __set__ e __delete__. Se um desses mtodos for definido para um objeto, ele ser considerado um descritor. Observe melhor esses mtodos na Listagem 1. Lista 1. Mtodos de descritor
__get__(self, instance, owner) __set__(self, instance, value) __delete__(self, instance)

No qual: __get__ acessa o atributo. Ele retorna o valor do atributo, ou gera a exceo AttributeError se o atributo solicitado no est presente. __set__ chamado em uma operao de designao de atributo. Ele no retorna nada. __delete__ controla uma operao de excluso. Ele no retorna nada. importante observar que descritores so designados a uma classe e no a uma instncia. Se a classe for modificada, o prprio descritor ser substitudo ou excludo e no ter seu cdigo acionado. Voltar para parte superior

Quando descritores so necessrios Considere um atributo email. necessrio verificar se o formato do email est correto antes de designar um valor ao atributo. Esse descritor permite que o email seja processado por meio de uma expresso regular e que seu formato seja validado antes de ser designado a um atributo. Em muitos outros casos, os descritores de protocolo do Python controlam o acesso a atributos, como a proteo do atributo name. Voltar para parte superior Criando descritores possvel criar descritores de vrias formas: Criando uma classe e substituindo qualquer um dos mtodos de descritor: __set__, __ get__ e __delete__. Esse mtodo usado quando necessrio o mesmo descritor em vrias classes e atributos diferentes (por exemplo, para validao de tipo). Usando um tipo de propriedade, que uma maneira mais simples e flexvel de usar um descritor. Usando o poder dos decoradores de propriedade, que so uma combinao de mtodo de tipo de propriedade e decoradores do Python. Todos os exemplos abaixo so semelhantes do ponto de vista operacional. A diferena est na implementao. Voltar para parte superior Criando descritores usando mtodos de classe A Listagem 2 demonstra a simplicidade do controle de designao de atributos no Python. Lista 2. Criando descritores usando mtodos de classe
class Descriptor(object): def __init__(self): self._name = '' def __get__(self, instance, owner): print "Getting: %s" % self._name return self._name def __set__(self, instance, name): print "Setting: %s" % name self._name = name.title() def __delete__(self, instance): print "Deleting: %s" %self._name del self._name class Person(object): name = Descriptor()

Use esse cdigo e veja a sada:


>>> user = Person() >>> user.name = 'john smith' Setting: john smith >>> user.name

Getting: John Smith 'John Smith' >>> del user.name Deleting: John Smith

Uma classe de descritor foi criada substituindo os mtodos __set__(), __get__() e __delete__() da classe-pai de forma que get imprimir Getting delete imprimir Deleting set imprimir Setting e altera o valor do atributo para o ttulo (primeira letra em maisculas, as demais em minscula) antes da designao. Isso til, por exemplo, ao armazenar e imprimir nomes. A converso para maisculas tambm pode ser movida para o mtodo __get__(). O _value ter o valor original e ser convertido a ttulo na solicitao get. Voltar para parte superior Criando descritores usando tipo de propriedade Embora o descritor especificado na Listagem 2 seja vlido e funcional, outro mtodo de criao por meio do tipo de propriedade. Com property(), fcil criar um descritor utilizvel para qualquer atributo. A sintaxe para a criao de property() property(fget=None, fset=None, fdel=None, doc=None) no qual: fget mtodo get do atributo fset mtodo set do atributo fdel mtodo delete do atributo doc docstring

Reescreva o exemplo usando a propriedade, como na Listagem 3. Lista 3. Criando descritores usando tipo de propriedade
class Person(object): def __init__(self): self._name = '' def fget(self): print "Getting: %s" % self._name return self._name def fset(self, value): print "Setting: %s" % value self._name = value.title() def fdel(self): print "Deleting: %s" %self._name del self._name name = property(fget, fset, fdel, "I'm the property.")

Use esse cdigo e veja a sada:


>>> user = Person() >>> user.name = 'john smith' Setting: john smith

>>> user.name Getting: John Smith 'John Smith' >>> del user.name Deleting: John Smith

O resultado claramente o mesmo. Observe que os mtodos fget, fset e fdel so opcionais, mas, se um deles no for especificado, a exceo AttributeError ser gerada ao tentar realizar a respectiva operao. Por exemplo, uma propriedade name declarada com None como fsete, em seguida, o desenvolvedor tenta designar valor ao atributo name. A exceoAttributeError gerada. Isso pode ser usado para definir atributos de leitura no sistema.
name = property(fget, None, fdel, "I'm the property") user.name = 'john smith'

Sada:
Traceback (most recent call last): File stdin, line 21, in mdule user.name = 'john smith' AttributeError: can't set attribute

Voltar para parte superior Criando descritores usando decoradores de propriedade Descritores podem ser criados com decoradores do Python, como na Listagem 4. Um decorador do Python uma alterao especfica na sintaxe da linguagem que permite uma alterao mais conveniente de funes e mtodos. Nesse caso, mtodos de gerenciamento de atributos so alterados. Para saber mais sobre o aplicativo de decoradores do Python, consulte o artigo do developerWorks, Decorators make magic easy. Lista 4. Criando descritores com decoradores de propriedade
class Person(object): def __init__(self): self._name = '' @property def name(self): print "Getting: %s" % self._name return self._name @name.setter def name(self, value): print "Setting: %s" % value self._name = value.title() @name.deleter def name(self): print ">Deleting: %s" % self._name

del self._name

Voltar para parte superior Criando descritores no tempo de execuo Todos os exemplos anteriores funcionam com o atributo name. A limitao dessa abordagem a necessidade de substituir separadamente __set__(), __get__() e __delete__() para cada atributo. A Listagem 5 apresenta uma soluo possvel para quando um desenvolvedor deseja incluir atributos de propriedade no tempo de execuo. A soluo usa o tipo de propriedade para desenvolver um descritor de dados. Lista 5. Criando descritores no tempo de execuo
class Person(object): def addProperty(self, attribute): # create local setter and getter with a particular attribute name getter = lambda self: self._getProperty(attribute) setter = lambda self, value: self._setProperty(attribute, value) # construct property attribute and add it to the class setattr(self.__class__, attribute, property(fget=getter, \ fset=setter, \ doc="Auto-generated method")) def _setProperty(self, attribute, value): print "Setting: %s = %s" %(attribute, value) setattr(self, '_' + attribute, value.title()) def _getProperty(self, attribute): print "Getting: %s" %attribute return getattr(self, '_' + attribute)

Vamos experimentar com este cdigo:


>>> user = Person() >>> user.addProperty('name') >>> user.addProperty('phone') >>> user.name = 'john smith' Setting: name = john smith >>> user.phone = '12345' Setting: phone = 12345 >>> user.name Getting: name 'John Smith' >>> user.__dict__ {'_phone': '12345', '_name': 'John Smith'}

Esse cdigo criou os atributos name e phone no tempo de execuo. Eles podem ser acessados pelo nome correspondente, mas so armazenados no dicionrio de namespace de objetos como _name e _phone, conforme especificado no mtodo _setProperty. Basicamente, name e phone acessam os atributos _name e _phone internos. Voc pode apresentar uma dvida em relao a um atributo _name no sistema quando o

desenvolvedor tenta incluir o atributo de propriedade name. A resposta que ele substituir o atributo _name atual com o novo atributo de propriedade. Esse cdigo permite controlar a forma como os atributos so tratados dentro de uma classe. Voltar para parte superior Concluso Os descritores do Python permitem um gerenciamento de atributos eficiente e flexvel com novas classes de estilo. Em conjunto com decoradores, eles permitem uma programao elegante, possibilitando a criao de Setters e Getters e de atributos de leitura. Tambm permite executar validao de atributos mediante solicitao por valor ou por tipo. Descritores podem ser aplicados em muitas reas, mas use-os com prudncia para evitar o cdigo desnecessariamente complexo que resultado da substituio do comportamento normal de um objeto. Recursos Aprender Guia do Python - Chamando Descritores: saiba como aplicar descritores nessa seo do guia do Python. Guia do Python - Implementando Descritores: explore a implementao de descritores nessa seo do guia do Python. Propriedades do Python: leia esta explicao sobre as propriedades do Python. Decorators make magic easy (David Mertz, developerWorks, dezembro de 2006): examine os decoradores do Python e seus recursos para metaprogramao. A rea de Software Livre no developerWorks fornece muitas informaes sobre ferramentas de software livre e de como utilizar tecnologias de software livre. Na zona Linux do developerWorks, encontre vrios artigos de instrues e tutoriais, bem como downloads, fruns de discusso e muitos outros recursos para desenvolvedores e administradores Linux. especializadas em artigos que abrangem diversas solues baseada na web. Fique por dentro dos Eventos tcnicos e webcasts do developerWorks com nfase em uma srie de produtos IBM e tpicos do segmento de mercado de TI. Participe de um briefing gratuito do developerWorks Live! para se informar sobre os produtos e ferramentas IBM, alm das tendncias do mercado de TI. Acompanhe as demos on demand do developerWorks , que abrangem desde demos de instalao e configurao de produtos para iniciantes at funcionalidades avanadas para desenvolvedores experientes. Siga o developerWorks no Twitter. Obter produtos e tecnologias Avalie produtos IBM da maneira que for melhor para voc: faa download da verso de teste de um produto, avalie um produto online, use-o em um ambiente de nuvem ou passe algumas horas na SOA Sandbox para saber mais sobre como implementar arquitetura orientada a servio (SOA) de maneira eficiente. Discutir Confira blogs do developerWorks e participe da comunidade do developerWorks.

Participe da comunidade do developerWorks. Entre em contato com outros usurios do developerWorks e explore os blogs, fruns, grupos e wikis voltados para desenvolvedores. Sobre o autor

Alex engenheiro de controle de qualidade no laboratrio de desenvolvimento da IBM Austrlia. Ele projeta e desenvolve casos de teste em Python, realiza o controle de qualidade e oferece suporte para teste da equipe de desenvolvimento de dispositivos de segurana da IBM.

Você também pode gostar