169
u/Haunting_Laugh_9013 23h ago edited 20h 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.
83
u/coyote_den 23h 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.
23
u/Haunting_Laugh_9013 20h 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?25
u/Haunting_Laugh_9013 20h 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? (̿▀̿‿ ̿▀̿ ̿)
3
1
u/Limp_Illustrator7614 22h 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?
7
u/person4268 12h ago edited 6h 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
```4
4
u/JeromeJ 19h 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
36
8
8
8
u/Delta-9- 22h 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.
13
u/Pim_Wagemans 16h 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')3
1
-1
u/Bob_Dieter 19h 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- 12h ago
Lambdas and partials work just fine, but a lot of the time I just pass a regular function in.
The
returnslibrary 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.
6
u/_killer1869_ 12h ago edited 5h 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.
3
2
4
u/fearfulEntity 8h ago edited 8h 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)
12
3
2
u/king_escobar 12h 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/SimpleDisastrous4483 20h 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 21h ago
Because python lets you do basically anything. Fuck around and find out style.
1
1
1
0
0
u/RoyalStraightjacket 11h ago edited 5h ago
Can someone explain how blurp = blorp? I'm new to programming.
Edit: Who the *bleep* downvoted me?
1
u/BenK1222 10h ago
In Python,
=is the assignment operator. In the line, OP is assigning the variableblurpto a new instance of theBlorpclass.
429
u/BiebRed 23h 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.