Specifically, in the case of constructors, via <class>(...).
Is there an alternative API? No. This is public API regardless of anyone's intentions. Though "it's weird" is really not a very strong argument against it.
def foo(... # public
def _foo(... # internal
def __foo(... # munged
def __foo__(... # magic
Internal is more convention as the language doesn't really do anything with it, but it does with munged, and magic methods are specifically for things implemented in the language.Internal and munged don't exactly map to private and protected, but are kinda similar ish.
In any case I actually like how one can use underscores to point on how exposed some method is supposed to be. Makes it simpler to actually know what to skip and what not.
Admittedly it's obnoxious when you've got habits for one and you're on a team that uses another--totally flies in the face of the zen re: "there should be only one obvious way to do things".
...but that was always a rather ambitious goal anyway. I'm ok navigating the forest of alternative API's if it means not being locked into something that I can only change by choosing an entirely different language. I'm happy that it's very easy to tell when somebody is mucking about with python internals vs when they're mucking about with some library or other.
I think it's fairly short sighted to criticize these. FWIW, I also did that the first time I wrote Python. Other languages that do similar things provide a useful transparency.
I've had snippets in my editor for approximately 15 years at this point so I don't have to manually type any of the dunder methods. Would recommend!
Which, between them, covers approximately everyone.
Same-other-language-user:
((()))()()()({}{}{{(((())){}}}}{}{}{};;;;();)(;}}}
*not supposed to be correct syntax, it's just a joke
Ugliness is not the point of hi-vis vests lol, the point is to not get shot by other hunters.
By contrast, I find a well camouflaged deer quite beautiful--once I notice it at all. The beauty comes from the way that it is so clearly a thing of its surroundings. Nothing at all like a bright orange hat.
Sure... yes the bright orange is ugly, but it's not the ugliness that prevents you from getting shot, it's the bright unnatural color. Other hunters aren't thinking "oh that's really ugly, it must not be something I can shoot" they're thinking "bright orange means person, I should not fire my rifle in that direction".
> If it wasn't, it wouldn't grab my attention so well.
Are you saying that if you thought the bright orange was pretty it wouldn't occur to you not to fire your gun in its direction?
If you call something "stupid" it doesn't really convey anything meaningful, especially not in the way you're using there, it comes across as "I don't actually have a reason I don't like it, I just don't".
The programming languages world is broad/varied enough that any statement like "no other language does this!" is almost certainly wrong (outside of esoteric languages, which python and php most certainly are not)
__add, __sub, __mul, __div, __mod, __pow, __unm, __idiv
__band, __bor, __bxor, __bnot, __shl, __shr
__concat, __len
__eq, __lt, __le
__index, __newindex, __call
__gc, __close, __mode, __namehttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
so it settled on having this syntax for similar cases using "Symbol":
class Foo { *[Symbol.iterator]() { yield 1; yield 2; yield 3; } }
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macro...
Now you don't need to write your double-underscore methods ever again, if you don't want to.
IMO this is less horrendous than e.g. go's insistence that exported functions are indicated by a capital letter - that really affects code using the module not just the definition.
Ruby has the same thing but it’s called ‘new’.
Implementing the type of customization (idiomatically) that __new__ provides in Kotlin and JS isn’t any cleaner.
This hasn't been true since Python 3.3. You no longer need a __init__.py for Python to recognize a module, but it can still be useful in many cases.
> The __init__.py files are required to make Python treat directories containing the file as packages (unless using a namespace package, a relatively advanced feature).
I wrote it in about an hour and a half. It seems to work in Python 3.6 and 3.12. Now you never need to write another double-underscore magic method again.
But who cares? It's syntax, it has its purpose.
Kotlin: constructor is either part of class definition or keyword constructor.
Ruby: initialize
JS: constructor
Python: ______new______, _______init_______
Literally this meme: https://knowyourmeme.com/memes/three-headed-dragon