__str__ versus __unicode__
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
The __str__ versus __unicode__ question is mostly a Python 2 compatibility topic. In modern Python 3 code, __unicode__ does not exist as part of the data model, and __str__ should return normal Unicode text. The confusion comes from old Python 2 code, where byte strings and Unicode strings were different types and object display methods had to account for both.
How It Worked In Python 2
Python 2 had two important text-like types:
- '
strfor byte strings' - '
unicodefor Unicode text'
Because of that split, classes sometimes implemented both __str__ and __unicode__.
A legacy Python 2 style class might look like this:
In that world:
- '
unicode(obj)called__unicode__' - '
str(obj)expected a byte string from__str__'
That design existed because Python 2 could not treat all text as one unified Unicode type.
How It Works In Python 3
Python 3 simplified the model. str is Unicode text, so __str__ should return a str object and that is usually all you need.
There is no separate __unicode__ hook to implement in normal Python 3 code.
If you need a byte representation in Python 3, the relevant method is __bytes__, not __unicode__.
Where __repr__ Fits In
This topic is often easier to understand when you place __repr__ beside __str__.
- '
__str__is the readable, user-facing representation' - '
__repr__is the developer-facing representation used for debugging when possible'
In modern code, that pairing matters much more than __str__ versus __unicode__.
Porting Old Code Safely
When migrating Python 2 code, the safest mental model is to remove the old byte-versus-Unicode split from your object methods. Keep text as Unicode internally and make __str__ return that text directly.
If legacy code used __unicode__ as the source of truth, you can usually fold that logic into __str__ during the port and delete the older method entirely. That tends to simplify the class and remove a whole category of encoding mistakes.
The only time you still need special handling is when code must emit raw bytes for a protocol or file format, and that belongs in __bytes__ or an explicit encoding step, not in __str__.
What To Do In Real Code Today
If you are writing Python 3, implement __str__ when you want a readable string form. Ignore __unicode__ entirely unless you are maintaining Python 2 compatibility code, which is rare now.
If you are maintaining old Python 2 code, the common historical pattern was:
- put the real text logic in
__unicode__ - have
__str__return encoded bytes derived from it
But that pattern should stay in legacy maintenance, not in new Python 3 code.
Common Pitfalls
The most common mistake is trying to implement __unicode__ in Python 3 and expecting it to be called. It will not be part of normal string conversion.
Another issue is returning bytes from __str__ in Python 3. __str__ must return a text str, not bytes.
Developers also sometimes use __str__ for debugging-heavy output when __repr__ would be more appropriate. The two methods serve different audiences.
Finally, when porting Python 2 code, test every place that used implicit string conversion. Old byte-oriented assumptions often break during migration.
Summary
- '
__unicode__is mainly a Python 2 concept tied to the oldunicodetype.' - In Python 3, implement
__str__for readable Unicode text output. - Use
__bytes__if you need a byte representation in modern code. - '
__repr__is usually the more relevant companion to__str__today.' - Do not carry Python 2 string patterns into new Python 3 code unless you truly maintain legacy compatibility.
Related reading
- _csv.Error field larger than field limit 131072
- _pickle.PicklingError Could not serialize object TypeError can't pickle _thread.RLock objects
- _tkinter.TclError no display name and no DISPLAY environment variable
- / vs // for division in Python
- A B without arithmetic operators, Python vs C
- A clean, lightweight alternative to Python''s twisted?
- A clean, lightweight alternative to Python''s twisted?
- A column-vector y was passed when a 1d array was expected
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.