4 ms·
Go has this. Python has this (_ access). package-private allows you to write tests if the tests are in the same namespace (Java langs). Class Access Modifiers
by Supermancho 3y ago
Go has this. Python has this (_ access). package-private allows you to write tests if the tests are in the same namespace (Java langs).
Class Access Modifiers were for controlling property and method inheritance, which has been bastardized into "CAMs tell you the API", because it's convenient. An object's API can be defined by an interface (following traditional OOP conventions), allowing CAMs to be used for their original orthogonal purpose. In practice, developers don't want to make an interface when they can slap a CAM on it and say "good enough". Some language don't even support interfaces, pushing the practice. So here we are with the wrong abstraction.
- scruple 3y ago> Python has this (_ access). What exactly is being referenced here?
- Supermancho 3y ago> I wish that my programming languages had a "public for testing only" scope. > Python has this (_ access) Bypassing CAMs is useful for testing. Python has a mechanism, which is used for that^...regardless of the intent of the feature. ^Underscores are a partially enforced convention for private methods. If your import stripped your access to an attribute, you can still access via __getattribute__() which reaches into the hierarchy. There are other tricks as well. You might call this a special method lookup.
- BerislavLopac 3y agoAnd which mechanism is that exactly?
- edgyquant 3y agoThe one they clearly explained in the comment, using __get_attribute__
- deleted 3y ago[deleted]
- BerislavLopac 3y agoYes, clearly explained in the update to the comment made after my question. :/
- deleted 3y ago[deleted]
- Supermancho 3y agoI edited the comment for clarity and there is no formal name that I can find, unfortunately.
- BerislavLopac 3y agoI still don't understand what you're talking about. > If your import stripped your access to an attribute Python doesn't have class access modifiers, and in particular import does not strip access to attributes in Python. There are two ways Python modifies behaviour in the presence of leading underscores: 1. If there is a module attribute (i.e. a variable in a module) starting with an underscore, it will not be imported when doing `import * from some_module` -- which is not recommended anyway. Importing `some_module` directly will give normal access to the attribute, as `some_module._foo`. 2. If a class or instance attribute's name begins with a double underscore, it will not be accessible directly; however its name is simply mungled at compile time: > class Foo: > __foobar = "__foobar" > > def __init__(self): > self.__bar = "__bar" > self.__baz__ = "__baz__" > > Foo.__foobar AttributeError: 'Foo' object has no attribute '__foobar' > foo = Foo() > foo.__bar AttributeError: 'Foo' object has no attribute '__bar' > Foo._Foo__foobar '__foobar' > foo._Foo__bar '__bar' > # Note that does not hold for attributes both starting and ending in double underscores > # (so-called 'dunder' attributes): foo.__baz__ '__baz__' You are correct that underscores are a convention, but in Python one simply cannot count on the kind of access control that exists in other languages, especially when writing code that is supposed to be executed in unknown contexts (i.e. a library). When writing tests, one presumably has full control over both the code and the execution context, so this kinds of tricks can be used relatively safely; that being said, test runners like pytest tend to provide their own abstractions and tools around those tricks anyway.
- Supermancho 3y ago_single_leading_underscore: weak “internal use” indicator. E.g. from M import * does not import objects whose names start with an underscore. - https://peps.python.org/pep-0008/ https://peps.python.org/pep-0008/ Ironically, there's a story on the frontpage of HN right now, regarding attribute handling in python, which may be of interest: https://lwn.net/SubscriberLink/943619/eaa8a4496fcba1fd/ https://lwn.net/SubscriberLink/943619/eaa8a4496fcba1fd/
- Lio 3y agoRuby also has this. e.g. you can use send to call private methods during testing (and then use static analysis like rubocop to ensure only public_send is used in production). You also can simulate it in JavaScript by using a closure and a separate package for your "private" functions. By mixing the "private" code into the closure you can make it private in usage but still available to unit tests.