Sitemap
Pythonic AF

Join our smart community of Python developers! This is your no-BS guide to mastering Python, deep dives, hot takes, clean code, dirty bugs, and everything in between. From automation to APIs, web apps to AI, we cover real world tips, performance tricks, and more.

Acually lot of them are Types

7 min readJan 10, 2026

--

I keep seeing people talk about Python as if it’s this endless ecosystem of packages and imports.

And sure, that’s true.

But there’s also a surprisingly large chunk of Python that’s just… already there.

No installs. No imports. No ceremony.

Global names that exist the moment the interpreter starts.

There are 71 of them.

Technically some aren’t functions, some are types, but in practice they all behave the same way: you can call them, rely on them, and forget they’re even special.

This isn’t a tutorial.

It’s more like a guided walk through what’s actually built into Python, with opinions and a few reality checks along the way.

Math-ish stuff (and numeric types)

Let’s start with the obvious ones

bool, int, float, complex, max, min, divmod, abs, pow, round, sum

Some of these are types pretending to be functions.

Some are functions pretending to be obvious.

bool only has two values. You already know that.

What people forget is that calling bool(x) is really about asking “is this truthy?”, and you can control that for your own objects with __bool__.

That matters more than people think.

int, float, and complex are the same story: types first, converters second.

If you define __int__, __float__, or __complex__, you’re deciding how your object behaves when it touches the numeric world.

complex still uses j for the imaginary unit.

That’s not changing. Complaining won’t help.

max and min are more flexible than beginners realize.

They work on any iterable, but the multi-argument form is often clearer when you’re dealing with a fixed set of values.

divmod is one of those functions that feels pointless until you actually need both the quotient and remainder.

Then it’s suddenly the cleanest option.

abs works on more than numbers. For complex values, it returns the magnitude.

For your own objects, __abs__ lets you define what “absolute” even means.

pow is mostly the ** operator, except for the optional third argument.

Modular exponentiation isn’t flashy, but it’s dramatically more efficient when numbers get big.

round deserves suspicion. Floating point rounding in Python does not behave like grade school rounding.

If that surprises you, good, it should.

sum is obvious, but also quietly useful for counting things.

Summing booleans is a thing. It’s fine. Don’t overthink it.

Collections you already use

dict, list, tuple, set, frozenset

These are types, not utilities.

You usually create them with literals, not by calling the constructor directly.

tuple being immutable isn’t just a philosophical choice.

It’s why tuples can be dictionary keys and set elements, and lists can’t.

set exists primarily to delete duplicates and test membership fast.

Anything beyond that is bonus.

frozenset is the least-used one here, but it fills a very specific gap: an immutable set.

Same logic as tuples vs lists.

If you’ve never needed it, that’s normal.

Strings, bytes, and things adjacent to pain

bytes, bytearray, str, memoryview, open

bytes is basically a tuple of integers from 0 to 255, except it also pretends to be a string when that’s convenient.

bytearray is the mutable version.

If you’ve never needed to mutate raw bytes, you can ignore it without guilt.

str in Python is Unicode. This is one of Python’s best decisions and one of the reasons text handling is mostly tolerable.

Yes, you can paste emoji directly into source code. That’s intentional.

memoryview is where things get weird.

It’s Python’s way of exposing raw buffers as structured data without copying. Most people never touch it.

People writing C extensions do. That’s fine.

open is unavoidable. Use it with a with block.

Anything else is just asking for file descriptor leaks.

Conversions and representations

chr, ord, bin, oct, hex, format, input, ascii, repr

chr and ord are inverses. Unicode, not just ASCII, despite the names.

bin, oct, and hex return strings. If you want the number back, int(value, base) already knows how.

format is more central than it looks.

F-strings and str.format both rely on it. If you implement __format__, you’re opting into that whole ecosystem.

input blocks.

It always returns a string. If that annoys you, that’s your problem, not Python’s.

repr is supposed to be unambiguous, not pretty. ascii is basically repr with escape sequences enforced.

Get Rishikant Sharma’s stories in your inbox

Join Medium for free to get updates from this writer.

Neither one exists for user facing text.

Iteration tools you half-remember

iter, next, enumerate, zip, reversed, sorted, filter, map

iter and next are what for loops are built on. You don’t call them often, but they’re always there.

enumerate saves you from manual index tracking.

If you’re doing range(len(x)), you probably want this instead.

zip stops at the shortest input. That’s not a bug.

reversed works on dictionaries now. That still surprises people.

sorted always returns a list.

Even if you pass in a set or tuple. That’s a deliberate choice.

filter and map are lazy. I know they’re “functional”.

I still prefer list comprehensions most of the time. Readability wins.

More iteration (and async versions)

all, any, range, slice, aiter, anext

all([]) is True. any([]) is False. If that feels wrong, think harder.

range is lazy and cheap. Stop converting it to lists unless you need to.

slice is rarely written directly, but it shows up when you implement __getitem__.

It’s how slicing actually works.

aiter and anext exist for async iteration.

You almost never call them directly. async for handles it.

Debugging and interactivity

breakpoint, help, print

breakpoint() drops you into a debugger. It’s fine in emergencies.

Your IDE is usually better.

help() is still underrated. It’s ugly, but it’s honest.

print does more than people think.

The file argument alone saves a lot of nonsense.

Objects, identity, and introspection

object, getattr, setattr, delattr, hasattr, dir, id

Using object() as a sentinel is a pattern worth remembering.

It’s the cleanest way to represent “not provided”.

The getattr / setattr family exists for dynamic access. If attribute names are coming from variables, this is how you do it.

dir is a hint, not a promise.

id is about identity, not equality.

If you really care about object identity, is is usually clearer.

Types and behavior checks

hash, len, isinstance, issubclass, callable, super, type

hash exists so dictionaries can be fast. That’s the point.

isinstance beats direct type checks almost every time. Subclasses matter.

Yes, bool is a subclass of int. No, that’s not a mistake.

callable is simple and useful.

super is not magic, but it does require understanding method resolution order. Multiple inheritance makes this messy.

type can inspect types or create them dynamically.

The second use is powerful and rarely needed.

Descriptors you use without noticing

property, classmethod, staticmethod

property is how attribute access becomes behavior.

You’re not “breaking encapsulation”, you’re defining it.

classmethod receives the class, not the instance.

That matters when inheritance enters the picture.

staticmethod is just a function living on a class. No magic. No context.

Dynamic features you should be suspicious of

eval, exec, compile, globals, locals, vars, __import__

These are sharp tools.

eval evaluates expressions. exec runs statements. Both can ruin your day if misused.

If you’re executing the same code repeatedly, compile exists for a reason.

globals() returns the actual global namespace. Modifying it modifies reality.

locals() lies to you if you try to write to it.

vars() exposes __dict__.

Sometimes that’s useful. Sometimes it’s a footgun.

__import__ works, but you almost never want it. importlib is the grown up alternative.

That’s all of them.

Some you use every day. Some you’ll never touch.

Knowing they exist doesn’t make you a better developer, but knowing when not to use them probably does.

If nothing else, it’s a reminder that Python already gives you a lot, and sometimes the best abstraction is just not adding another one.

If you see it differently, or there’s one you think deserves more (or less) respect,

I’m curious how other people actually use these in real code.

--

--

Written by Rishikant Sharma

Python developer, I enjoy turning complex problems into simple, elegant solutions. Python is my go to language for making ideas come to life.

Published in Pythonic AF

Join our smart community of Python developers! This is your no-BS guide to mastering Python, deep dives, hot takes, clean code, dirty bugs, and everything in between. From automation to APIs, web apps to AI, we cover real world tips, performance tricks, and more.