r/programminghorror • • 4d ago

why can i do this

Post image
1.2k Upvotes

60 comments sorted by

621

u/BiebRed 4d ago

Because Python is secretly a meta language under the hood that will let you implement any other programming language within its runtime and there are infinite ways for you to abuse its trust.

105

u/DevBoiAgru 4d ago

Does this mean if I learn python I know every language ever possible?

146

u/Bronzdragon 4d ago

"No, Neo. I'm trying to tell you that when you're ready, you won't have to."

  • Morpheus, talking about Python.

27

u/andynzor 4d ago

So... just a worse Common Lisp?

18

u/rolfn 3d ago

4

u/SakishimaHabu 3d ago edited 3d ago

Oh shit! I've been thinking this for years. I didn't know it had a name.

14

u/ZackyZack 4d ago

So it's just Tcl with more steps?

7

u/Delta-9- 4d ago

And actual data types

2

u/ZackyZack 3d ago

Tcl has data type too! String is a data type!

1

u/Delta-9- 3d ago

Technically true!

6

u/overclockedslinky 3d ago

assuming this other language uses specifically python syntax and adds no additional features of any kind

2

u/Glum-Echo-4967 4d ago

question is, what use do I have for such abilty?

2

u/Snudget 3d ago

With some hacks you can replace builtin types like str and int, make them behave like JavaScript

1

u/amo_pessoas_peladas 4d ago

So... Why is python not rust

1

u/stilldebugging 3d ago

It never trusted you.

218

u/Haunting_Laugh_9013 4d ago edited 4d ago

basically what it's doin is basically the blurp.hello_world doesn't actually call any method, it gets interpreted as a field access. The field access goes to the getattribute dunder method, and the argument fn is the name of the attribute (in this case "hello_world"). After that, it returns a lambda that calls whatever function that is passed into the lambda that is from the python builtins. So getattribute returns a lambda that gets the print function from the builtins, printing whatever the name of the field that was accessed.

113

u/coyote_den 4d ago

Python exposes just about every internal aspect of itself and lets you override everything, so you can make getting an attribute return a function with the attribute name as the argument.

If you left off the (“print”) the result would be <function <lambda>>, but that immediately calls the lambda function and prints the result.

34

u/Haunting_Laugh_9013 4d ago

yerp. if i wanted to make it a bit more readable, i guess i could do something like (blurp.hello_world)("print"), but why would I want that?

33

u/Haunting_Laugh_9013 4d ago

"There should be one-- and preferably only one --obvious way to do it." - The Zen of Python ```python def prent(streng: str):
blurp = Blorp() getattr(blurp, streng)("print")

prent("hello world!") print("hello world!") ```

Whatcha think of that Guido? (̿▀̿‿ ̿▀̿ ̿)

4

u/Silpheel 4d ago

It would have been even better with “preent” and “streeng”, imo XD

4

u/Limp_Illustrator7614 4d ago edited 3d ago

Python exposes just about every internal aspect of itself and lets you override everything

i mean, not really. that description fits ruby more. you cant override stuff like int and list cuz they're implemented in c for performance i think?

EDIT: today i learned

18

u/person4268 4d ago edited 3d ago

Not if you reach into the C with ctypes, then you can rearrange for instance, the values of the cached int instances of common numbers:

```python Python 3.14.7 (main, Aug 10 2026, 07:46:56) [GCC 16.1.1 20260728] on linux

Type "help", "copyright", "credits" or "license" for more information.

import ctypes ... def deref(addr, typ): ... return ctypes.cast(addr, ctypes.POINTER(typ)) ... deref(id(29), ctypes.c_int)[6] = 100

29 100 28 + 1 100
```

10

u/SirCheesington 3d ago

that's fucking evil dude hahahahaha

7

u/JeromeJ 4d ago

I'm not gonna add anything but rephrase (it might aid comprehension for some as this is a complex topic) :

Upon accessing helloworld (before it is even called), __getattribute_ will return a lamba (this is all good since that's what we want to do with it! Call it!). Specifically, it's a closure that captures the name of the attribute we tried to access (here "hello_world") and, specifically, looks like it will give that as a first parameter to 'something' upon being invoked.

When we finally call hello_world, the lamba runs and getattr go fetch the built-in based on the parameter we called hello_world with (here "print") then immediately invoke it with the parameter that was captured earlier ("hello_world").

As to why Python allows you to do that, I'd say that Python treats you as an adult and let you do your own things.. Even if it could be ill advised. Python is a scripting language so it's good to whip out things quickly and it's fine to have dirty hacky bits of code to get things done.

In other contexts, it'd probably best to avoid doing black magic like that but it can be useful.

1

u/mypetocean 3d ago

See also Ruby's method_missing hook method.

43

u/eruanno321 4d ago

In C, array[3] and 3[array] are the same thing by definition.

21

u/Delta-9- 4d ago

Makes me think of libraries that override __or__ so you can write Python that looks like bash, where you're piping things into other things. I've honestly been tempted to use them, but I don't want to curse the next dev to touch my code base with something so unexpected—it's bad enough I use monads.

26

u/Pim_Wagemans 4d ago

pathlib from the standard library overrides __div__ to let you extend paths like this:

>>> import pathlib
>>> path = pathlib.Path("/home")

>>> path_2 = path / "user" / ".local"

>>> path_2
PosixPath('/home/user/.local')

6

u/fearfulEntity 3d ago

... and that's actually pretty neat and readable

1

u/Yadobler 2d ago

This is so c++. It always bugged me to do that but fstrings would be quite messy too and putting them in an array and merging is too excessive. Plus this way also allows pathlib to escape characters that one might forget or not know how to do when trying to handle path strings with variables

0

u/BenK1222 3d ago

This is a crime against humanity

1

u/itzNukeey 3d ago

How are you using monads in python?

2

u/Delta-9- 3d ago

Mostly for chaining together functions where one or more of them may raise or return a None, but the equivalent if-else blocks would be tedious to write or hard to read for their sheer number. I've tried using them for dependency injection, but the resulting code seemed so foreign to Python I've decided not to use it.

1

u/Zandegok 2d ago

Xonsh allows you execute bash and python in the same line

0

u/Bob_Dieter 4d ago

How do you use monad in python? To use monads in an ergonomic way, you need to be able to create many small-ish continuation functions, and pythons syntax for that is horseshit.

1

u/Delta-9- 4d ago

Lambdas and partials work just fine, but a lot of the time I just pass a regular function in.

The returns library also did something clever with list comprehension syntax to emulate do-notation in Haskell. I don't use it much, but it makes long chains look much simpler.

11

u/_killer1869_ 4d ago edited 3d ago

Python gives the programmer a lot of freedom, which also means the programmer must know restraint. This is a perfect example of just because you can, doesn't mean you should, but overwriting __getattribute__ can sometimes be useful in niche cases.

Using it to dynamically swap a builtin function and its parameter to be each other is, obviously, abuse of the freedom the language provides.

7

u/HaroerHaktak 4d ago

It can be one because it can be. Please do not question it.

8

u/sarc-tastic 4d ago

Why not

6

u/fearfulEntity 3d ago edited 3d ago

Maybe I'm getting kinda old, but... what's the point? Yes, you can do that and yes that's completely valid code. Usefulness cleanliness and readability is another question. The language itself allows you implementng much more cursed things and it's completely on your behalf to create maintainable project with provided tools. Like any other language tbh (But in python it can be much more easily visualized with code snippets like this one)

5

u/Kadabrium 4d ago

why does c++ allow overloading -> but not .

5

u/Yankas 3d ago

You can write horrible code that's just as bad or worse in any programming language.

14

u/chimneydecision 4d ago

On second thought, let us not go to Python. ‘Tis a silly language.

3

u/SoloMaker 4d ago

You can also do this in Lua

3

u/king_escobar 4d ago

You can do this because in python, literally everything is an object. Including modules, including class definitions, including functions. And since literally everything is an object, you can dynamically change literally everything including changing things like properties of modules and classes and functions.

2

u/Professional-Ad-5032 3d ago

you can do this, doesn't mean you should do this.

2

u/trollpolado 3d ago

What font is that?

2

u/Haunting_Laugh_9013 3d ago

iosevka

1

u/DesiresQuiet 3d ago

Great font choice. Thank you.

3

u/RoyalStraightjacket 3d ago edited 3d ago

Can someone explain how blurp = blorp? I'm new to programming.

Edit: Who the *bleep* downvoted me?

2

u/BenK1222 3d ago

In Python, = is the assignment operator. In the line, OP is assigning the variable blurp to a new instance of the Blorp class.

2

u/SimpleDisastrous4483 4d ago

I love it. Python is so hilariously permissive, and this is a very fun way to do dumb things with it

1

u/realmauer01 4d ago

Because python lets you do basically anything. Fuck around and find out style.

1

u/Cheap-Cut7910 4d ago

Python is basically chaos wrapped in syntax.

1

u/MurkyWar2756 echo "Sub Mod" && :(){ :|:& };: 1d ago

This is the first, or maybe second, time I see an exit fullscreen icon followed by "Potential Spam" next to a comment.

-1

u/lmg1337 4d ago

When I see a language letting you do things like this, I think to myself: "What a silly language".
I know a lot of people like Python, but I wouldn't want to use it for software development, just for helper scripts.

0

u/PythonNoob999 4d ago

I lub python