This will add some overhead for every single call to such wrapped function. If you use that extensively for many classes, won't that be a huge performance degradation?
It would maybe be nice to have a flag so that these wrappings apply only in test or debug mode.
Also, it works e.g. by using `inspect.currentframe().f_back.f_back`. I'm not sure if that is such a clean and stable solution. (See e.g. here: https://github.com/amitassaraf/lang/blob/master/src/lang/acc...) E.g. when you add other wrappers around your function, I'm quite sure that this would break.
This is an impressive library, but I don't really see the usefulness. That is either because I'm a Python programmer, and Java semantics aren't useful in Python, or because I'm a Python programmer, and I haven't used Java semantics, so I wouldn't know.
I can say, though, that I've never had problems with something accessing private variables that it shouldn't have. The meaning of private variables in Python isn't "don't access anything that starts with an underscore", rather it's "you're accessing these variables at your own risk".
This "we're all adults" model has worked out very well for my use cases. Can anyone share a few cases where hard constraints here would be beneficial?
> I can see the value in quickly knowing if new code is mucking with private/protected properties.
Would this do it?
re.findall(r'(?<!self)\._\w+', sourcelines)
Anytime you're using ``obj._foo`` and it's not ``self._foo`` that suggests you're mucking about with the internals of an object that the author didn't expect you to use.
Well, for your future reference, Pylint (https://www.pylint.org/) checks for that and many other common pitfalls. I'm sure its competitors PyChecker and Pyflakes do so as well.
This makes me a little sad. So, a few observations:
- The use of metaclasses for (almost?) every feature in this library makes it prone to metaclass conflicts. What if I want to inherit from two classes that use two different features from the library?
>>> class MetaOne(type):
... pass
...
>>> class MetaTwo(type):
... pass
...
>>> class One(metaclass=MetaOne):
... pass
...
>>> class Two(metaclass=MetaTwo):
... pass
...
>>> class Both(One, Two):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
- I've never had a problem with other programmers accidentally changing my "constants" (eg. THE_THINGS_IN_ALL_CAPS) and I've never had a problem with other programmers accidentally changing my "private" attributes (eg. _prepended_with_underscore). Naming conventions are good enough for those purposes, in my experience.
- And when they're not, there's __name_mangling, which is sufficient to avoid the need for a 'final'. Compilers can make use of 'final', which is why final exists in Cython. I'm not sure the purpose in pure Python.
- There's no need for the distinction between an Abstract class and and Interface. Python already supports multiple inheritance of abstract classes.
A little off topic, but it's possible to automatically resolve metaclass conflicts in cases like this (e.g. construct a minimal suitable metaclass on the fly) :)
I agree - enforcing some of these best practices as a lint step would be more useful than crashing at run time. The benefit of these features in Java/C++ is that they catch problems at compile time.
I appreciate the work that went into this. But as a Python guy, this really seems like a solution in search of a problem--a problem that was already identified by the language and addressed.
??? Go write Java if you want to write Java. Don't try to write Java with Python syntax. Use Python to write Python.
Trying to force the idioms of the programming language you just left onto the programming language you just learned is the classic sign of not having put any effort whatsoever into learning the idioms of the new programming language.
I don't really understand why people want to make Python something which is not. Python is not Java, if you want to use Java constructs, use Java! That simple.
20 comments
[ 2.9 ms ] story [ 56.8 ms ] threadIt would maybe be nice to have a flag so that these wrappings apply only in test or debug mode.
Also, it works e.g. by using `inspect.currentframe().f_back.f_back`. I'm not sure if that is such a clean and stable solution. (See e.g. here: https://github.com/amitassaraf/lang/blob/master/src/lang/acc...) E.g. when you add other wrappers around your function, I'm quite sure that this would break.
I can say, though, that I've never had problems with something accessing private variables that it shouldn't have. The meaning of private variables in Python isn't "don't access anything that starts with an underscore", rather it's "you're accessing these variables at your own risk".
This "we're all adults" model has worked out very well for my use cases. Can anyone share a few cases where hard constraints here would be beneficial?
I can see the value in quickly knowing if new code is mucking with private/protected properties.
Would this do it?
Anytime you're using ``obj._foo`` and it's not ``self._foo`` that suggests you're mucking about with the internals of an object that the author didn't expect you to use.I'm not actively looking for a solution, just noting this might be more well received if you could easily turn it off and on.
Edit: Again, not looking for solutions. I thought the feedback of being able to turn it on/off might be useful for the OP.
- The use of metaclasses for (almost?) every feature in this library makes it prone to metaclass conflicts. What if I want to inherit from two classes that use two different features from the library?
- I've never had a problem with other programmers accidentally changing my "constants" (eg. THE_THINGS_IN_ALL_CAPS) and I've never had a problem with other programmers accidentally changing my "private" attributes (eg. _prepended_with_underscore). Naming conventions are good enough for those purposes, in my experience.- And when they're not, there's __name_mangling, which is sufficient to avoid the need for a 'final'. Compilers can make use of 'final', which is why final exists in Cython. I'm not sure the purpose in pure Python.
- There's no need for the distinction between an Abstract class and and Interface. Python already supports multiple inheritance of abstract classes.
So yeah, props for the effort, but I don't see it being actually used.
Trying to force the idioms of the programming language you just left onto the programming language you just learned is the classic sign of not having put any effort whatsoever into learning the idioms of the new programming language.
> Lang was built using a Java like mindset
I don't really understand why people want to make Python something which is not. Python is not Java, if you want to use Java constructs, use Java! That simple.
Being more like Java is about the last thing in the world python needs.
FYI This was just a fun thing to experiment with, never claimed this would be useful or is the right thing to use :)