Python language basics 76: class property setters

Introduction

In the previous post we looked at class level methods. We saw that they weren’t much different from “normal” methods. The fact that the first input parameter is “self” is what differentiates class level methods. Also, they can be called on an instance of a class, i.e. an instantiated object. The extra properties that the method needs are provided after “self”.

In this post we’ll look at a special group of class methods: setters.

Setters

We saw before that there is no mechanism in Python to hide class properties:

class Person:

    def __init__(self, name, age):        
        self._name = name
        self._age = age

The _name and _age properties will be accessible to external consumers of the class:

person = Person("John", 100)
person._name = "Not John"
print(person._name)

This prints “Not John”. In Python it’s customary to indicate class level properties with an underscore “_” in front. It’s a signal to other programmers that they should not directly access these elements.

How can the person’s name be modified then after the object initialisation step? If you’d like to make the _name field modifiable then you can create a class level method with the same name bar the underscore:

def name(self, name):
        self._name = name

Alternatively you can specifically call the method “set” followed by the property name:

def set_name(self, name):
        self._name = name

This is more like the Java way of doing it and may be frowned upon by Python experts.

Here comes a general note: setters and their “cousins”, the getters are not as straightforward to implement like in strictly typed languages like Java or C#. You’ll find multiple implementation types for Python if you search the Internet.

This is an example of a setter: a method designed to set the value of a class level variable. It’s really not different from normal class level methods but it has a different purpose. The above example is probably as easy as it gets as far as setters are concerned. The incoming value is simply assigned to the corresponding class level property. You are free to extend it of course, e.g. with some validation:

def name(self, name):
        if name == "" or str(name).isspace():
            raise ValueError("Person's name must not be empty.")
        self._name = name

Bear in mind though that there may not be a setter for every property of a class. It’s not uncommon to let certain values of a class to be set once, usually through the initialiser and then never again during the object’s lifetime. If you don’t see a matching setter then it may as well mean that the property is either immutable or read-only or that the details of changing the value of the property are hidden within the class. External consumers are not supposed to directly access the “private” variables as there may be complex rules attached to how they are allowed to change.

E.g. consider the position of the front wheels of a car when turning. A Car object might have an initialiser to set the initial position of the wheels, i.e. their angles. However, it’s not wise to create setters for those wheels. It’s better to create other methods such as “turn_left” and “turn_right” that internally modify the angles of the front wheels. External callers of the class should not be able to modify the wheels’ position independently. The “turn” methods are analogous to turning the steering wheel. That operation is best implemented by the internal mechanics of the car. Imagine having to set the angles of the front wheels yourself. You would end up in an accident very quickly.

So always be careful whether or not it’s necessary to add setters to a class. Ask yourself whether the external caller can be wise enough to modify the value of a class level property.

In the next post we’ll look at the “cousin” of setters, i.e. the getters.

Read all Python-related posts on this blog here.

Advertisements

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

the software architecture

thoughts, ideas, diagrams,enterprise code, design pattern , solution designs

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Cyber Matters

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: