SlideShare a Scribd company logo
Descriptors
Python's most obscure language feature demystified.
In 5 minutes.
Chris Beaumont
@BeaumontChris
graduate student, astrophysics
Harvard University / University of Hawaii
Learning about descriptors
creates an appreciation
for the elegance of Python's design.
-Raymond Hettinger
Learning about descriptors
creates an appreciation
for the elegance of Python's design.
-Raymond Hettinger
I DON'T
GET IT
class Email(object):
def __init__(self, sender, subject, message):
self.sender_widget = QLineEdit(sender)
self.subject_widget = QLineEdit(subject)
self.message_widget = QLineEdit(message)
How does other code
interact with
email data?
class Email(object):
...
def get_subject(self):
return self.subject_widget.text()
def set_subject(self, subject):
self.subject_widget.setText(subject)
...
e = Email()
e.set_subject('Hi there')
sub = e.get_subject()
class Email(object):
...
def get_subject(self):
return self.subject_widget.text()
def set_subject(self, subject):
self.subject_widget.setText(subject)
...
e = Email()
e.set_subject('Hi there')
sub = e.get_subject()
Gross
Properties
Disguise methods
as attributes
http://www.flickr.com/photos/mkapple/741018101/
class Email(object):
...
@property
def subject(self):
return self.subject_widget.text()
@subject.setter
def subject(self, subject):
self.subject_widget.setText(subject)
...
e = Email()
sub = e.subject
e.subject = 'hi there'
class Email(object):
...
@property
def subject(self):
return self.subject_widget.text()
@subject.setter
def subject(self, subject):
self.subject_widget.setText(subject)
...
e = Email()
sub = e.subject
e.subject = 'hi there'
class Email(object):
...
@property
def subject(self):
return self.subject_widget.text()
@subject.setter
def subject(self, subject):
self.subject_widget.setText(subject)
...
Nice.
class Email(object):
def __init__(self, sender, subject, message):
self._sender_widget = QLineEdit(sender)
self._subject_widget = QLineEdit(subject)
self._message_widget = QLineEdit(message)
@property
def sender(self):
return self._sender_widget.text()
@sender.setter
def sender(self, sender):
self._sender_widget.setText(sender)
@property
def subject(self):
return self._subject_widget.text()
@subject.setter
def subject(self, subject):
self._subject_widget.setText(subject)
@property
def message(self):
return self._message_widget.text()
@message.setter
def message(self, message):
self._message_widget.setText(message)
class Email(object):
def __init__(self, sender, subject, message):
self._sender_widget = QLineEdit(sender)
self._subject_widget = QLineEdit(subject)
self._message_widget = QLineEdit(message)
@property
def sender(self):
return self._sender_widget.text()
@sender.setter
def sender(self, sender):
self._sender_widget.setText(sender)
@property
def subject(self):
return self._subject_widget.text()
@subject.setter
def subject(self, subject):
self._subject_widget.setText(subject)
@property
def message(self):
return self._message_widget.text()
@message.setter
def message(self, message):
self._message_widget.setText(message)
Gross
Descriptors
Reusable Properties
http://www.freeimageslive.co.uk/files/images005/locust_leaf.JPG
class TextWrapper(object):
def __init__(self, widget_name):
self.widget_name = widget_name
def __get__(self, object):
widget = getattr(object, self.widget_name)
return widget.text()
def __set__(self, object, value):
widget = getattr(object, self.widget_name)
widget.setText(value)
class Email(object):
sender = TextWrapper('sender_widget')
subject = TextWrapper('subject_widget')
message = TextWrapper('message_widget')
def __init__(self, sender, subject, message):
self.sender_widget = QLineEdit(sender)
self.subject_widget = QLineEdit(subject)
self.message_widget = QLineEdit(message)
...
...
class TextWrapper(object):
def __init__(self, widget_name):
self.widget_name = widget_name
def __get__(self, object):
widget = getattr(object, self.widget_name)
return widget.text()
def __set__(self, object, value):
widget = getattr(object, self.widget_name)
widget.setText(value)
class Email(object):
sender = TextWrapper('sender_widget')
subject = TextWrapper('subject_widget')
message = TextWrapper('message_widget')
def __init__(self, sender, subject, message):
self.sender_widget = QLineEdit(sender)
self.subject_widget = QLineEdit(subject)
self.message_widget = QLineEdit(message)
e = Email()
sender = e.sender
e.sender = 'foo'
...
...
e = Email()
sender = e.sender
e.sender = 'foo'
...
class TextWrapper(object):
def __init__(self, widget_name):
self.widget_name = widget_name
def __get__(self, object):
widget = getattr(object, self.widget_name)
return widget.text()
def __set__(self, object, value):
widget = getattr(object, self.widget_name)
widget.setText(value)
class Email(object):
sender = TextWrapper('sender_widget')
subject = TextWrapper('subject_widget')
message = TextWrapper('message_widget')
def __init__(self, sender, subject, message):
self.sender_widget = QLineEdit(sender)
self.subject_widget = QLineEdit(subject)
self.message_widget = QLineEdit(message)
e = Email()
sender = e.sender
e.sender = 'foo'
class TextWrapper(object):
def __init__(self, widget_name):
self.widget_name = widget_name
def __get__(self, object):
widget = getattr(object, self.widget_name)
return widget.text()
def __set__(self, object, value):
widget = getattr(object, self.widget_name)
widget.setText(value)
class Email(object):
sender = TextWrapper('sender_widget')
subject = TextWrapper('subject_widget')
message = TextWrapper('message_widget')
def __init__(self, sender, subject, message):
self.sender_widget = QLineEdit(sender)
self.subject_widget = QLineEdit(subject)
self.message_widget = QLineEdit(message)
e = Email()
sender = e.sender
e.sender = 'foo'
Nice.
class TextWrapper(object):
def __init__(self, widget_name):
self.widget_name = widget_name
def __get__(self, object):
widget = getattr(object, self.widget_name)
return widget.text()
def __set__(self, object, value):
widget = getattr(object, self.widget_name)
widget.setText(value)
class Email(object):
sender = TextWrapper('sender_widget')
subject = TextWrapper('subject_widget')
message = TextWrapper('message_widget')
def __init__(self, sender, subject, message):
self.sender_widget = QLineEdit(sender)
self.subject_widget = QLineEdit(subject)
self.message_widget = QLineEdit(message)
e = Email()
sender = e.sender
e.sender = 'foo'
Nice.
Nice.
class TextWrapper(object):
def __init__(self, widget_name):
self.widget_name = widget_name
def __get__(self, object):
widget = getattr(object, self.widget_name)
return widget.text()
def __set__(self, object, value):
widget = getattr(object, self.widget_name)
widget.setText(value)
class Email(object):
sender = TextWrapper('sender_widget')
subject = TextWrapper('subject_widget')
message = TextWrapper('message_widget')
def __init__(self, sender, subject, message):
self.sender_widget = QLineEdit(sender)
self.subject_widget = QLineEdit(subject)
self.message_widget = QLineEdit(message)
e = Email()
sender = e.sender
e.sender = 'foo'
Nice.
Nice.
Meh?class TextWrapper(object):
def __init__(self, widget_name):
self.widget_name = widget_name
def __get__(self, object):
widget = getattr(object, self.widget_name)
return widget.text()
def __set__(self, object, value):
widget = getattr(object, self.widget_name)
widget.setText(value)
class Email(object):
sender = TextWrapper('sender_widget')
subject = TextWrapper('subject_widget')
message = TextWrapper('message_widget')
def __init__(self, sender, subject, message):
self.sender_widget = QLineEdit(sender)
self.subject_widget = QLineEdit(subject)
self.message_widget = QLineEdit(message)
Go forth
and refactor
Python Descriptors Demystified
Descriptor
Recipes
http://epicthings.net/wp-content/uploads/2011/09/Cookie-Monster-Cookie.jpg
Instance-specific data
class Foo(object):
x = Descriptor()
f1 = Foo()
f2 = Foo()
f1.x = 5
f2.x = 4
class Descriptor(object):
def __init__(self):
self._data = {}
def __get__(self, instance):
return self._data[instance]
Accessing Descriptor
Methods
class Descriptor(object)
def __get__(self, instance):
if instance == None:
return self
def cool_descriptor_method(self):
pass
desc = Foo.x # instance = None
desc.cool_descriptor_method()

More Related Content

PDF
Python programming : Classes objects
PDF
Python programming : Inheritance and polymorphism
PDF
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PDF
Python unit 3 m.sc cs
PPTX
Python: Basic Inheritance
PDF
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
Python programming : Classes objects
Python programming : Inheritance and polymorphism
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
Python unit 3 m.sc cs
Python: Basic Inheritance
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲

What's hot (20)

PPTX
Advance OOP concepts in Python
PPTX
Python OOPs
PPTX
Python oop third class
PDF
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
KEY
Building a Pluggable Plugin
PPTX
Basics of Object Oriented Programming in Python
PPTX
Ch8(oop)
KEY
jQuery+Drupal Optimizations
PDF
1st CI&T Lightning Talks: Writing better code with Object Calisthenics
PDF
Doctrator Symfony Live 2011 Paris
PDF
Doctrator Symfony Live 2011 San Francisco
PPTX
CLASS OBJECT AND INHERITANCE IN PYTHON
PPTX
Python – Object Oriented Programming
PPTX
Object Oriented Programming in Python
PDF
0php 5-online-cheat-sheet-v1-3
PDF
아이폰강의(3)
PDF
Delegate
PPT
Spsl v unit - final
PDF
Your Entity, Your Code
PPT
Class and Objects in PHP
Advance OOP concepts in Python
Python OOPs
Python oop third class
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
Building a Pluggable Plugin
Basics of Object Oriented Programming in Python
Ch8(oop)
jQuery+Drupal Optimizations
1st CI&T Lightning Talks: Writing better code with Object Calisthenics
Doctrator Symfony Live 2011 Paris
Doctrator Symfony Live 2011 San Francisco
CLASS OBJECT AND INHERITANCE IN PYTHON
Python – Object Oriented Programming
Object Oriented Programming in Python
0php 5-online-cheat-sheet-v1-3
아이폰강의(3)
Delegate
Spsl v unit - final
Your Entity, Your Code
Class and Objects in PHP
Ad

Similar to Python Descriptors Demystified (20)

PDF
Object_Oriented_Programming_Unit3.pdf
PPTX
Empower your App by Inheriting from Odoo Mixins
KEY
Pyimproved again
PDF
Declarative Data Modeling in Python
PPTX
DOM and Events
PPTX
Python_Object_Oriented_Programming.pptx
PPTX
Python-oop
KEY
PyCon US 2012 - State of WSGI 2
PPTX
cbse class 12 Python Functions2 for class 12 .pptx
PPTX
Basic_concepts_of_OOPS_in_Python.pptx
PPTX
Module-5-Classes and Objects for Python Programming.pptx
PDF
Ruby Development and MongoMapper (John Nunemaker)
PPTX
Improving Correctness with Types Kats Conf
PPTX
Powerful Generic Patterns With Django
PPTX
Introduce oop in python
PDF
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
PPT
Introduction to Python - Part Three
PDF
Descriptor Protocol
PDF
Descriptor Protocol
PDF
Functions2.pdf
Object_Oriented_Programming_Unit3.pdf
Empower your App by Inheriting from Odoo Mixins
Pyimproved again
Declarative Data Modeling in Python
DOM and Events
Python_Object_Oriented_Programming.pptx
Python-oop
PyCon US 2012 - State of WSGI 2
cbse class 12 Python Functions2 for class 12 .pptx
Basic_concepts_of_OOPS_in_Python.pptx
Module-5-Classes and Objects for Python Programming.pptx
Ruby Development and MongoMapper (John Nunemaker)
Improving Correctness with Types Kats Conf
Powerful Generic Patterns With Django
Introduce oop in python
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Introduction to Python - Part Three
Descriptor Protocol
Descriptor Protocol
Functions2.pdf
Ad

Recently uploaded (20)

PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
Machine Learning_overview_presentation.pptx
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
cuic standard and advanced reporting.pdf
PDF
Encapsulation_ Review paper, used for researhc scholars
PPTX
A Presentation on Artificial Intelligence
PDF
Electronic commerce courselecture one. Pdf
PDF
Approach and Philosophy of On baking technology
PPT
Teaching material agriculture food technology
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Digital-Transformation-Roadmap-for-Companies.pptx
Machine Learning_overview_presentation.pptx
A comparative analysis of optical character recognition models for extracting...
cuic standard and advanced reporting.pdf
Encapsulation_ Review paper, used for researhc scholars
A Presentation on Artificial Intelligence
Electronic commerce courselecture one. Pdf
Approach and Philosophy of On baking technology
Teaching material agriculture food technology
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
MIND Revenue Release Quarter 2 2025 Press Release
Spectral efficient network and resource selection model in 5G networks
Unlocking AI with Model Context Protocol (MCP)
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Chapter 3 Spatial Domain Image Processing.pdf
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Network Security Unit 5.pdf for BCA BBA.
Review of recent advances in non-invasive hemoglobin estimation
Diabetes mellitus diagnosis method based random forest with bat algorithm

Python Descriptors Demystified

  • 1. Descriptors Python's most obscure language feature demystified. In 5 minutes. Chris Beaumont @BeaumontChris graduate student, astrophysics Harvard University / University of Hawaii
  • 2. Learning about descriptors creates an appreciation for the elegance of Python's design. -Raymond Hettinger
  • 3. Learning about descriptors creates an appreciation for the elegance of Python's design. -Raymond Hettinger I DON'T GET IT
  • 4. class Email(object): def __init__(self, sender, subject, message): self.sender_widget = QLineEdit(sender) self.subject_widget = QLineEdit(subject) self.message_widget = QLineEdit(message) How does other code interact with email data?
  • 5. class Email(object): ... def get_subject(self): return self.subject_widget.text() def set_subject(self, subject): self.subject_widget.setText(subject) ... e = Email() e.set_subject('Hi there') sub = e.get_subject()
  • 6. class Email(object): ... def get_subject(self): return self.subject_widget.text() def set_subject(self, subject): self.subject_widget.setText(subject) ... e = Email() e.set_subject('Hi there') sub = e.get_subject() Gross
  • 8. class Email(object): ... @property def subject(self): return self.subject_widget.text() @subject.setter def subject(self, subject): self.subject_widget.setText(subject) ...
  • 9. e = Email() sub = e.subject e.subject = 'hi there' class Email(object): ... @property def subject(self): return self.subject_widget.text() @subject.setter def subject(self, subject): self.subject_widget.setText(subject) ...
  • 10. e = Email() sub = e.subject e.subject = 'hi there' class Email(object): ... @property def subject(self): return self.subject_widget.text() @subject.setter def subject(self, subject): self.subject_widget.setText(subject) ... Nice.
  • 11. class Email(object): def __init__(self, sender, subject, message): self._sender_widget = QLineEdit(sender) self._subject_widget = QLineEdit(subject) self._message_widget = QLineEdit(message) @property def sender(self): return self._sender_widget.text() @sender.setter def sender(self, sender): self._sender_widget.setText(sender) @property def subject(self): return self._subject_widget.text() @subject.setter def subject(self, subject): self._subject_widget.setText(subject) @property def message(self): return self._message_widget.text() @message.setter def message(self, message): self._message_widget.setText(message)
  • 12. class Email(object): def __init__(self, sender, subject, message): self._sender_widget = QLineEdit(sender) self._subject_widget = QLineEdit(subject) self._message_widget = QLineEdit(message) @property def sender(self): return self._sender_widget.text() @sender.setter def sender(self, sender): self._sender_widget.setText(sender) @property def subject(self): return self._subject_widget.text() @subject.setter def subject(self, subject): self._subject_widget.setText(subject) @property def message(self): return self._message_widget.text() @message.setter def message(self, message): self._message_widget.setText(message) Gross
  • 14. class TextWrapper(object): def __init__(self, widget_name): self.widget_name = widget_name def __get__(self, object): widget = getattr(object, self.widget_name) return widget.text() def __set__(self, object, value): widget = getattr(object, self.widget_name) widget.setText(value) class Email(object): sender = TextWrapper('sender_widget') subject = TextWrapper('subject_widget') message = TextWrapper('message_widget') def __init__(self, sender, subject, message): self.sender_widget = QLineEdit(sender) self.subject_widget = QLineEdit(subject) self.message_widget = QLineEdit(message) ... ...
  • 15. class TextWrapper(object): def __init__(self, widget_name): self.widget_name = widget_name def __get__(self, object): widget = getattr(object, self.widget_name) return widget.text() def __set__(self, object, value): widget = getattr(object, self.widget_name) widget.setText(value) class Email(object): sender = TextWrapper('sender_widget') subject = TextWrapper('subject_widget') message = TextWrapper('message_widget') def __init__(self, sender, subject, message): self.sender_widget = QLineEdit(sender) self.subject_widget = QLineEdit(subject) self.message_widget = QLineEdit(message) e = Email() sender = e.sender e.sender = 'foo' ... ...
  • 16. e = Email() sender = e.sender e.sender = 'foo' ... class TextWrapper(object): def __init__(self, widget_name): self.widget_name = widget_name def __get__(self, object): widget = getattr(object, self.widget_name) return widget.text() def __set__(self, object, value): widget = getattr(object, self.widget_name) widget.setText(value) class Email(object): sender = TextWrapper('sender_widget') subject = TextWrapper('subject_widget') message = TextWrapper('message_widget') def __init__(self, sender, subject, message): self.sender_widget = QLineEdit(sender) self.subject_widget = QLineEdit(subject) self.message_widget = QLineEdit(message)
  • 17. e = Email() sender = e.sender e.sender = 'foo' class TextWrapper(object): def __init__(self, widget_name): self.widget_name = widget_name def __get__(self, object): widget = getattr(object, self.widget_name) return widget.text() def __set__(self, object, value): widget = getattr(object, self.widget_name) widget.setText(value) class Email(object): sender = TextWrapper('sender_widget') subject = TextWrapper('subject_widget') message = TextWrapper('message_widget') def __init__(self, sender, subject, message): self.sender_widget = QLineEdit(sender) self.subject_widget = QLineEdit(subject) self.message_widget = QLineEdit(message)
  • 18. e = Email() sender = e.sender e.sender = 'foo' Nice. class TextWrapper(object): def __init__(self, widget_name): self.widget_name = widget_name def __get__(self, object): widget = getattr(object, self.widget_name) return widget.text() def __set__(self, object, value): widget = getattr(object, self.widget_name) widget.setText(value) class Email(object): sender = TextWrapper('sender_widget') subject = TextWrapper('subject_widget') message = TextWrapper('message_widget') def __init__(self, sender, subject, message): self.sender_widget = QLineEdit(sender) self.subject_widget = QLineEdit(subject) self.message_widget = QLineEdit(message)
  • 19. e = Email() sender = e.sender e.sender = 'foo' Nice. Nice. class TextWrapper(object): def __init__(self, widget_name): self.widget_name = widget_name def __get__(self, object): widget = getattr(object, self.widget_name) return widget.text() def __set__(self, object, value): widget = getattr(object, self.widget_name) widget.setText(value) class Email(object): sender = TextWrapper('sender_widget') subject = TextWrapper('subject_widget') message = TextWrapper('message_widget') def __init__(self, sender, subject, message): self.sender_widget = QLineEdit(sender) self.subject_widget = QLineEdit(subject) self.message_widget = QLineEdit(message)
  • 20. e = Email() sender = e.sender e.sender = 'foo' Nice. Nice. Meh?class TextWrapper(object): def __init__(self, widget_name): self.widget_name = widget_name def __get__(self, object): widget = getattr(object, self.widget_name) return widget.text() def __set__(self, object, value): widget = getattr(object, self.widget_name) widget.setText(value) class Email(object): sender = TextWrapper('sender_widget') subject = TextWrapper('subject_widget') message = TextWrapper('message_widget') def __init__(self, sender, subject, message): self.sender_widget = QLineEdit(sender) self.subject_widget = QLineEdit(subject) self.message_widget = QLineEdit(message)
  • 24. Instance-specific data class Foo(object): x = Descriptor() f1 = Foo() f2 = Foo() f1.x = 5 f2.x = 4 class Descriptor(object): def __init__(self): self._data = {} def __get__(self, instance): return self._data[instance]
  • 25. Accessing Descriptor Methods class Descriptor(object) def __get__(self, instance): if instance == None: return self def cool_descriptor_method(self): pass desc = Foo.x # instance = None desc.cool_descriptor_method()