> What are emphatically not pretty or useful are Python’s leading underscores to loosely enforce encapsulation.
IMO Go's use of upper/lower case is even worse than Python's use of underscores. What would be better? Explicitly labeling everything as `public` or `private`, C++/Java style?
> Does Python force you to pass [self] as an argument to make some kind of clever point?
I think the idea is that `a.foo(b)` should act similarly to `type(a).foo(a, b)`.
However, what happens when you define a method and miss off the `self` parameter is crazy. Inside a class, surely `def f(a, b): print(a, b)` should be a method that can be called with two arguments.
> And why are some classes (int, str, float) allowed to be lower case
Historical reasons. AFAIK in early versions of Python these weren't classes at all - the built-in types were completely separate.
> IMO Go's use of upper/lower case is even worse than Python's use of underscores.
Especially when serialising a struct to JSON - only public members are serialised, so your JSON ends up with a bunch of keys called Foo, so you have to override serialisation names on all the fields to get them lowercased.
Python's actual behavior in this case is far stranger than static methods, which are a standard feature of many object-oriented languages (albeit one that's fairly redundant in a language that allows free functions).
If you want `def foo(a, b)` inside a class to be a static method, you need to define it as
class Foo:
@staticmethod
def foo(a, b):
...
Now `f = Foo(); f.foo(1, 2)` will work.
However, you need to be explicit about this because it is much more common for this situation to arise because someone forgot a self somewhere than for it to have been intentional. Requiring @staticmethod serves to signal to humans that this odd behavior is intentional (but again I'd say that, stylistically, if you're using a staticmethod, just move it out of the class and into the module namespace, module namespaces in python don't bite).
I just don't think the decorator should be required for static methods. If you write `def foo(a, b)` inside a class, the lack of `self` should be sufficient to make `foo` a static method.
IMO it would make sense for Python to look at `a, b` and assume you wanted a static method with two parameters. Instead it assumes you're using `a` instead of `self` and really wanted an instance method with one parameter.
This requires blessing "self" as special (like this in java etc.). Python made a specific choice not to do that (and there are cases where you don't want to use "self", such as metaclasses, classmethods, and (rarely) nested classes that close over their parent class.
Like I said: most of the time, a missing `self` is an error by the user, and so python requires explicit notification both to the language, and to other people, that you're doing what you mean to do, and not just making a mistake.
I think that's the point: requiring the user to explicitly pass "self" rather than making it a language keyword mostly just gives the user an unnecessary opportunity to make mistakes.
Wouldn't it be more explicit if there was a designated keyword that objects could use to access their own members instead of implicitly assuming that any first argument to a method is a reference to them, only called 'self' by convention?
Honestly, I think it would have made some amount of sense to make super a method defined on the base object so that
def __init__(self, x, y):
self.super(x, y)
would be the convention. There may be some infra issue with this (and in general, `super` has to be kind of magical no matter how you handle it). But yes, in general I can vibe with "super is too implicit".
Ruby generally (I think? I haven't seen much of Ruby code) uses "@" instead of "self.", and "@@" instead of "ParticularClassName." (btw, "self.__class__" doesn't cut it), and it seems to produce no namespace pollution.
IMO Go's use of upper/lower case is even worse than Python's use of underscores. What would be better? Explicitly labeling everything as `public` or `private`, C++/Java style?
> Does Python force you to pass [self] as an argument to make some kind of clever point?
I think the idea is that `a.foo(b)` should act similarly to `type(a).foo(a, b)`.
However, what happens when you define a method and miss off the `self` parameter is crazy. Inside a class, surely `def f(a, b): print(a, b)` should be a method that can be called with two arguments.
> And why are some classes (int, str, float) allowed to be lower case
Historical reasons. AFAIK in early versions of Python these weren't classes at all - the built-in types were completely separate.