> It's more elegant firstly because it follow use

No it doesn't. Currently `def foo(self): pass` is called as `instance.foo()`. You're suggesting that `def self.foo(): pass` would be called as `instance.foo()`, except now it looks like self and instance are syntactically related in ways that they aren't.

> Again, "this" is just an identifier here, and doesn't have any special meaning.

But the grammar is no longer LL(1), and you have weird conditionally valid syntax, like `.` in a function name is valid only in a class block.

> "def foo(x)" has the same meaning both inside and outside of a class declaration

This is a stretch, especially since you're now optimizing for the uncommon case. Staticmethods are rare compared to instance methods (I'll go further and claim that static methods are an antipattern in python, modules are valid namespaces, you can stick a function in a module and couple it to a class also defined in that module and nothing bad will happen. Banning staticmethods entirely doesn't reduce expressiveness). Aligning staticmethods with functions, instead of aligning instance methods with functions (as python does currently) encourages you to do the wrong thing.

> classmethod

Your changes don't affect classmethod at all, if anything they'd make classmethod more of a special case. How do you signal that `self.foo()` takes `self` as the class instead of the instance?

> It's especially annoying when you have class attributes that happen to reference a function, because conversion from functions to methods is a runtime thing - so you have to remember to wrap those in staticmethod() as well.

What do you mean? Like

class Foo:
a = Foo.func()
@staticmethod
def func():
return 1

I'll say again: staticmethods are an antipattern in python:

def func()
return 1

class Foo:
a = func()

works just as well, better in fact. Modules are great namespaces. Classes are more than namespaces, and if all you need is a namespace, you shouldn't use a class.

> because conversion from functions to methods is a runtime thing

I'd also quibble with this: it's a binding thing.

class Foo:
a = Foo.foo(None)
def foo(self):
return 1

will work, and if you check, type(Foo.foo) is still just `function`, its only when you create an instance of Foo that the function `foo` is bound to the instance, and when that is done, the bound `foo` is converted to a method object. This was different in python2, where Foo.foo and instance.foo were both "instancemethod" objects, but in python3, Foo.foo is a plain old function, and instance.foo is a method.

Specifically this means that if you can get your hands on the `method` constructor (like with `type(instance.method)`), you can then do silly things like

class A():
def foo(self): pass
instance = A()
def f(self): return 5
assert instance.func() == 5

and this will work. You'll have bound the function to the instance. Of course, if you stick an attribute on `instance` (or `A`), and reference `self.attribute` in the function, this will still work. (this also lets you do things like bind a given instance of a function to a different instance of the class, but that's because the method constructor is essentially just partial with some bookkeeping for class information)