[Python-ideas] Re: Add support for private variables, methods and functions in Python
05.05.21 17:18, Shreyan Avigyan пише: > I don't know if it's worth adding private to python modules but what about > classes? Private in class is an important feature in OOP that Python lacks > (Most OOP languages have private like Java, C++, etc.). I don't know why it > was introduced in the first place but it's kind of a convention to have that > feature in OOP. Private fields in Python are no less private than in C++. In C++ you can read private fields: class User { public: string name; private: string password; }; class HackedUser { public: string name; string password; }; password = ((HackedUser*)&user)->password; Of course it is a bad practice. You should not write this in your code, and if your code allows executing arbitrary code in the same address space, your security is already gone. And the same is in Python. You can access private attributes, but usually you should not (except for debugging purpose). > Moreover why does private exist in the first place? If there's a reason then > shouldn't it apply to Python as well. Private exists as a mean of self-limitation. It allows you to separate your data and code on these which are purposed to be used outside of the module or the class, and these which aren't. For your own good you must follow this convention. The same reasons are applied to both C++ and Python. It is more complicated in Java, but its security model is not perfect in any case, and Python prefers the convenience of debugging and simplicity of implementation. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/6ITKZ45ZCUCWJVMPGVJJSDEXQ4TFZWQK/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Support more conversions in format string
On 06May2021 03:43, Dennis Sweeney wrote: >Maybe I'm missing something, but why do you need the SimpleNamespace at all? >Why not make your own mapping as in > >class StringMapper: >... >def __getitem__(self, s): ># Whatever arbitrary behavior you want ># Process suffixes, etc here, for example: >if s.endswith(".lc"): >return self.wrapped[s.removesuffix(".lc")].lower() >return self.wrapped[s] > > format_string.format_map(StringMapper(whatever)) > >Maybe then the data can just be data and this wrapper can handle all >the formatting conversions. All this is somewhat orthoganal to adding more !foo things. If we're not talking about extending the conversions, we should probably take this over to python-list, because the ":foo" stuff is just implementation. That said, because my tags can have dots in their names and I want to be able to write: {tag.name.with.dot} and this is accomplished with an elaborate SimpleNamespace subclass to make the .name.with.dot stuff work as attributes. Just don't ask :-( Oh, you did :-) Anyway, I may be shifting sideways per my recent ":foo" post, using a new class which is a magic view of the TagSet and a Formatter subclass which parses the field_names itself (thus grabbing the dotted identifier). Still a work in progress. Cheers, Cameron Simpson ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/WTCYMJAHIRDGPJCS4UDZRBCIHOWKDTJ7/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Support more conversions in format string
Maybe I'm missing something, but why do you need the SimpleNamespace at all? Why not make your own mapping as in class StringMapper: ... def __getitem__(self, s): # Whatever arbitrary behavior you want # Process suffixes, etc here, for example: if s.endswith(".lc"): return self.wrapped[s.removesuffix(".lc")].lower() return self.wrapped[s] format_string.format_map(StringMapper(whatever)) Maybe then the data can just be data and this wrapper can handle all the formatting conversions. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/RDS4KL7SUAP4AAA2XVBZTM5SZE4NUU46/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Support more conversions in format string
On 25Apr2021 10:54, Cameron Simpson wrote: >On 24Apr2021 22:35, Stephen J. Turnbull >wrote: >[...] >> > My use case is presupplied strings, eg a command line supplied >> > format string. >> >>In that case the format string is user input, and x is a variable in >>the program that the user can have substituted into their string? >> >>Assuming that *exact* use case, wouldn't >> >>>>> class LowerableStr(str): >>... def __format__(self, fmt): >>... if fmt == 'lc': >>...return self.lower() >>... else: >>...return str.__format__(self, fmt) >>... >>>>> "{x} is {x:lc} in lowercase".format_map({'x' : LowerableStr("This")}) >>'This is this in lowercase' >> >>do? > >You're perfectly correct. ":lc" can be shoehorned into doing what I ask. >But __format__ is in the wrong place for how I'd like to do this. Just to follow up on this, I've been experimenting with Stephen's suggestion of using ":foo" style format specifiers. With enough success that I'm probably going to run with it is I can make the implementation clean enough. I'm currently making a subclass of the Formatter builtin class, which supplies the string parser and lets one override various methods to implemenent the "{...}" parts. Currently I can do this: I've got a little ontology, saying that a tag named "colour" is "a colour, a hue" and expects to be a Python str. It also has metadata for the particular colour "blue". { 'type.colour': TagSet:{'description': 'a colour, a hue', 'type': 'str'}, 'meta.colour.blue': TagSet:{'url': 'https://en.wikipedia.org/wiki/Blue', 'wavelengths': '450nm-495nm'} } And I've got a tag set describing some object which is blue: {'colour': 'blue', 'labels': ['a', 'b', 'c'], 'size': 9} The TagSet class has a .format_as(format_string) method which hooks into the Formatter subclass and formats a string according to the TagSet. A little test programme to write information into some command line supplied format strings: [~/hg/css-tagsets(hg:tagsets)]fleet2*> py3 -m cs.tagset '{colour}' '{colour:meta}' '{colour:meta.url}' {colour} => 'blue' {colour:meta} => 'url="https://en.wikipedia.org/wiki/Blue"; wavelengths="450nm-495nm"' {colour:meta.url} => 'https://en.wikipedia.org/wiki/Blue' Looking promising to me. Cheers, Cameron Simpson ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/GGLPSQBFWM6FDR3DYEHSYSMGEBD5DBNU/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add support for private variables, methods and functions in Python
Hi Shreyan, You say: On Wed, May 05, 2021 at 02:18:55PM -, Shreyan Avigyan wrote: > I don't know if it's worth adding private to python modules but what > about classes? Private in class is an important feature in OOP that > Python lacks (Most OOP languages have private like Java, C++, etc.). I > don't know why it was introduced in the first place but it's kind of a > convention to have that feature in OOP. If you don't know why private was introduced, what makes you think it is a good feature to have? Programmers in languages with "private, protected" etc usually end up spending large amounts of time fighting with the compiler, because some over-zealous other programmers made things private that shouldn't have been. Python finds a nice middle ground between languages which offer no protection and those that encourage too much unnecessary protection. We have a very strong convention not to rely on or use other people's underscore variables, while still allowing people to inspect and even modify those variables if necessary; but if you really, truly want to hide the existence of class attributes you can write the class in C. Explain to us, what *exactly* are you worried about? Suppose you write a class, and have an underscore private attribute or method: class MyClass: def __init__(self): self._spam = 1 Now what? What are you worried about happening if somebody else gets access to your code, say they download it from Github or something, and use that private attribute? What harm are you trying to prevent? -- Steve ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/QO6CJ6ZQRWN2TOBBEPA3H3RVZ3F5MU4P/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Changing The Theme of Python Docs Site
I agree with the comment about removing full justification. Also, I think the Masonite docs' navigation is far superior to the Python docs. I like the full contents on the left, along with the version button, and the local jump on the right. The python docs require you to navigate somehwere else for the full contents. And, I don't undrstand why anyone would want "previous topic/next topic"—it's not like you're curling up with the Python docs before bed :) Finally, putting the docs in the center of the screen is better on today's giant monitors. On Tuesday, May 4, 2021 at 11:21:48 PM UTC-4 Jonathan Goble wrote: > On Tue, May 4, 2021 at 11:05 PM Mike Miller > wrote: > >> One thing that drives me nuts about the current Python docs >> theme is >> the FULL JUSTIFICATION that adds random spaces into each line to >> make the >> edges line >> up! >> >> Whatever y'all do, please remove that. :D I sometimes deactivate it in >> the >> browser dev tools but there it is again next refresh. >> > > Please. Full justification is nice with narrow columns like newspapers, > but on the web with wider paragraphs, it's annoying. I'd love to see it > yanked from the Python docs. > ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/ISTQ4PLQ3TNLXXL5BRWWJLI5PIDAGD33/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Namespaces!
On Wed, May 5, 2021, 02:11 Steven D'Aprano wrote: > My comments follow, interleaved with Matt's. > > > On Mon, May 03, 2021 at 11:30:51PM +0100, Matt del Valle wrote: > > > But you've pretty much perfectly identified the benefits here, I'll just > > elaborate on them a bit. > > > > - the indentation visually separates blocks of conceptually-grouped > > attributes/methods in the actual code (a gain in clarity when code is > read) > > Indeed, that is something I often miss: a way to conceptually group > named functions, classes and variables which is lighter weight than > separating them into a new file. > > But you don't need a new keyword for that. A new keyword would be nice, > but grouping alone may not be sufficient to justify a keyword. > > > > - the dot notation you use to invoke such methods improves the experience > > for library consumers by giving a small amount conceptually-linked > > autocompletions at each namespace step within a class with a large API, > > rather getting a huge flat list. > > We don't need a new keyword for people to separate names with dots. > > Although I agree with your position regarding nested APIs, *to a point*, > I should mention that, for what it is worth, it goes against the Zen: > > Flat is better than nested. > > > [...] > > - you can put functions inside a namespace block, which would become > > methods if you had put them in a class block > > This is a feature which I have *really* missed. > > > > - you don't have the same (in some cases extremely unintuitive) > > scoping/variable binding rules that you do within a class block (see the > > link in my doc). It's all just module scope. > > On the other hand, I don't think I like this. What I would expect is > that namespaces ought to be a separate scope. > > To give an example: > > def spam(): > return "spam spam spam!" > > def eggs(): > return spam() > > namespace Shop: > def spam(): > return "There's not much call for spam here." > def eggs(): > return spam() > > print(eggs()) > # should print "spam spam spam!" > print(Shop.eggs()) > # should print "There's not much call for spam here." > > > If we have a namespace concept, it should actually be a namespace, not > an weird compiler directive to bind names in the surrounding global > scope. > I agree with this. Great proposal though. > > > - it mode clearly indicates intent (you don't want a whole new class, > just > > a new namespace) > > Indeed. > > > > When using the namespaces within a method (using self): > > > > - It allows you to namespace out your instance attributes without needing > > to create intermediate objects (an improvement to the memory footprint, > and > > less do-nothing classes to clutter up your codebase) > > > > - While the above point of space complexity will not alway be relevant I > > think the more salient point is that creating intermediate objects for > > namespacing is often cognitively more effort than it's worth. And humans > > are lazy creatures by nature. So I feel like having an easy and intuitive > > way of doing it would have a positive effect on people's usage patterns. > > It's one of those things where you likely wouldn't appreciate the > benefits > > until you'd actually gotten to play around with it a bit in the wild. > > > I'm not entirely sure what this means. > > > > For example, you could rewrite this: > > > > class Legs: > > def __init__(self, left, right): > > self.left, self.right = left, right > > > > > > class Biped: > > def __init__(self): > > self.legs = Legs(left=LeftLeg(), right=RightLeg()) > > > > > > As this: > > > > class Biped: > > def __init__(self): > > namespace self.legs: > > left, right = LeftLeg(), RightLeg() > > > Oh, I hope that's not what you consider a good use-case! For starters, > the "before" with two classes seems to be a total misuse of classes. > `Legs` is a do-nothing class, and `self.legs` seems to be adding an > unnecessary level of indirection that has no functional or conceptual > benefit. > > I hope that the purpose of "namespace" is not to encourage people to > write bad code like the above more easily. > > > > And sure, the benefit for a single instance of this is small. But across > a > > large codebase it adds up. It completely takes away the tradeoff between > > having neatly namespaced code where it makes sense to do so and writing a > > lot of needless intermediate classes. > > > > SimpleNamespace does not help you here as much as you would think because > > it cannot be understood by static code analysis tools when invoked like > > this: > > > > class Biped: > > def __init__(self): > > self.legs = SimpleNamespace(left=LeftLeg(), right=RightLeg()) > > Surely that's just a limitation of the *specific* tools. There is no > reason why they couldn't be upgraded to understand SimpleNamespace. > > > [...] > > > 2. If __dict__ contains "B.C" a
[Python-ideas] Re: Add support for private variables, methods and functions in Python
See my comment here - https://mail.python.org/archives/list/python-ideas@python.org/message/L5LUQDNNV5ZTF4E33L2JSOYIKPJUJJK5/ ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/P5SBXBPZAXKHY75KKXWIAKPPSKGCYC3I/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add support for private variables, methods and functions in Python
I don't know if it's worth adding private to python modules but what about classes? Private in class is an important feature in OOP that Python lacks (Most OOP languages have private like Java, C++, etc.). I don't know why it was introduced in the first place but it's kind of a convention to have that feature in OOP. Moreover why does private exist in the first place? If there's a reason then shouldn't it apply to Python as well. And yes you're right the unprivileged code can just do the same thing. But I'm not only speaking of security in this context. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/L5LUQDNNV5ZTF4E33L2JSOYIKPJUJJK5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add support for private variables, methods and functions in Python
One issue with many common programming languages is that they appear to offer access protections via private/protected etc, but seldom do so securely (`private` modifiers are never, to my knowledge, intended to be a security mechanism). / Take for example C++: #include #include class Secrets { private: const std::string password; public: Secrets(const char * password): password(password) {} }; void consumer(Secrets &sec) { auto haxor = (const char *)&sec; for (size_t i=0; i<32; ++i) { std::cout << haxor + i << std::endl; } } int main() { Secrets sec("5exret_Paxxw0rd"); consumer(sec); return 0; } / It's fairly trivial to bypass the `private` access modified for member variables by reading the memory directly. Even with heap-allocated structures, this is not much harder to do. Likewise for Java: /// import java.lang.reflect.Field; import java.lang.NoSuchFieldException; class MyClass { private String password; MyClass(String password) { this.password = password; } } class Test { public static void main(String[] a) { MyClass mc = new MyClass("5exret_Paxxw0rd"); try{ Field f = MyClass.class.getDeclaredField("password"); f.setAccessible(true); System.out.println((String)f.get(mc)); } catch(Exception e) { } } } Some languages (Java) have optional security managers to try to avoid allowing such things, but they are not always perfect at preventing determined users. My advice would be to design your system to avoid trying to hide information from users who have the ability to run code from within the same address space as the secrets you're trying to protect. Thanks Steve On Wed, May 5, 2021 at 2:44 PM Shreyan Avigyan wrote: > Private methods, functions and variables are very common in programming > languages. But Python doesn't support private. It has conventions for > naming so considered private but not private. Most of the time private is > never required, what Python provides is more than enough. But the need for > private come into place when we're dealing with passphrases and servers. > For example consider this code, > > class A: > def get(): > // code to get the password > self.password = password > > Now consider this, > > >>> x = A(); x.get(); x.password > > See what just happened? Someone just got the member variable value that > the person wasn't supposed to. > > I suggest to add private support for functions (module __all__ methods to > be more clear), methods and variables (module __all__ variables or class > variables). > > (I very bad at reading PEPs so I may miss out something critical that's > been explained already (sometimes I miss out a feature in a PEP and think > about suggesting that feature when it's already there and then I realize > "Oh! It's already here in this PEP"). If that's the case then please > correct me.) > > With Regards, > Shreyan Avigyan > ___ > Python-ideas mailing list -- python-ideas@python.org > To unsubscribe send an email to python-ideas-le...@python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ > Message archived at > https://mail.python.org/archives/list/python-ideas@python.org/message/DD2L56GCOCWEUBBZBDKKKMPPVWB7PRFB/ > Code of Conduct: http://python.org/psf/codeofconduct/ > ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/ESC7EJS667JKJQ2SFKO6RBPHGFM32IAY/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add support for private variables, methods and functions in Python
On Wed, May 5, 2021 at 11:43 PM Shreyan Avigyan wrote: > > Private methods, functions and variables are very common in programming > languages. But Python doesn't support private. It has conventions for naming > so considered private but not private. Most of the time private is never > required, what Python provides is more than enough. But the need for private > come into place when we're dealing with passphrases and servers. For example > consider this code, > > class A: > def get(): > // code to get the password > self.password = password > > Now consider this, > > >>> x = A(); x.get(); x.password > > See what just happened? Someone just got the member variable value that the > person wasn't supposed to. > That's only a problem if you have untrusted code running in the same Python interpreter as privileged code. There's fundamentally no way that you can get the password without the untrusted code also being able to get it. Do you have an actual use-case where you have passphrases like this? How does the "code to get the password" do it, and how do you ensure that the unprivileged code can't just do the same thing? ChrisA ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/OEUKVHQO6WGKCNX462NJL4SJ6UNIWS3I/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add support for private variables, methods and functions in Python
Hey Shreyan, >From what I understand, Python's design focuses on enabling the developer to do whatever she feels right. Having a class attribute or something marked as "private" is more of a warning to people _using_ that class that they shouldn't tinker with that field. If I'm using a class that deals with a bank account, for example, and the current balance is marked as "private" - or prefixed with __, in Python - I should read that as "well, this value has some elaborated logic behind it. I should not go around messing with it because there may be consequences that this class's author didn't want" and not "I shouldn't be able to see this value!" This is not an information security aspect, it is more of a code usability thing. That said, > Someone just got the member variable value that the person wasn't supposed to If they can't access a piece of data, they shouldn't be allowed to execute code inside that server to begin with. There's actually a whole class of security flaws that deal with code execution. Once you allow someone to run code on your server, you're done and no keyword in the code will prevent bad things from happening. Best, --Bidu On Wed, May 5, 2021 at 10:41 AM Shreyan Avigyan wrote: > Private methods, functions and variables are very common in programming > languages. But Python doesn't support private. It has conventions for > naming so considered private but not private. Most of the time private is > never required, what Python provides is more than enough. But the need for > private come into place when we're dealing with passphrases and servers. > For example consider this code, > > class A: > def get(): > // code to get the password > self.password = password > > Now consider this, > > >>> x = A(); x.get(); x.password > > See what just happened? Someone just got the member variable value that > the person wasn't supposed to. > > I suggest to add private support for functions (module __all__ methods to > be more clear), methods and variables (module __all__ variables or class > variables). > > (I very bad at reading PEPs so I may miss out something critical that's > been explained already (sometimes I miss out a feature in a PEP and think > about suggesting that feature when it's already there and then I realize > "Oh! It's already here in this PEP"). If that's the case then please > correct me.) > > With Regards, > Shreyan Avigyan > ___ > Python-ideas mailing list -- python-ideas@python.org > To unsubscribe send an email to python-ideas-le...@python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ > Message archived at > https://mail.python.org/archives/list/python-ideas@python.org/message/DD2L56GCOCWEUBBZBDKKKMPPVWB7PRFB/ > Code of Conduct: http://python.org/psf/codeofconduct/ > ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/XORTSLR5K3VFG32LB6K523SYZKU7VKHF/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Add support for private variables, methods and functions in Python
Private methods, functions and variables are very common in programming languages. But Python doesn't support private. It has conventions for naming so considered private but not private. Most of the time private is never required, what Python provides is more than enough. But the need for private come into place when we're dealing with passphrases and servers. For example consider this code, class A: def get(): // code to get the password self.password = password Now consider this, >>> x = A(); x.get(); x.password See what just happened? Someone just got the member variable value that the person wasn't supposed to. I suggest to add private support for functions (module __all__ methods to be more clear), methods and variables (module __all__ variables or class variables). (I very bad at reading PEPs so I may miss out something critical that's been explained already (sometimes I miss out a feature in a PEP and think about suggesting that feature when it's already there and then I realize "Oh! It's already here in this PEP"). If that's the case then please correct me.) With Regards, Shreyan Avigyan ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/DD2L56GCOCWEUBBZBDKKKMPPVWB7PRFB/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Namespaces!
Thanks Paul, you channelled my thinking exactly correctly. I am not an expert on C++, but I think that's roughly how C++ namespaces work. Any C++ coders care to confirm or correct me? Steve On Wed, May 05, 2021 at 12:05:56PM +0100, Paul Moore wrote: > On Wed, 5 May 2021 at 11:33, Matt del Valle wrote: > > >> To give an example: > >> > >> def spam(): > >> return "spam spam spam!" > >> > >> def eggs(): > >> return spam() > >> > >> namespace Shop: > >> def spam(): > >> return "There's not much call for spam here." > >> def eggs(): > >> return spam() > >> > >> print(eggs()) > >> # should print "spam spam spam!" > >> print(Shop.eggs()) > >> # should print "There's not much call for spam here." > > > > > > I'm guessing this was a typo and you meant to type: > > > > print(spam()) > > # should print "spam spam spam!" > > print(Shop.spam()) > > # should print "There's not much call for spam here." > > > > Because if you did, then this is precisely how it would work under this > > proposal. :) > > I'm not the OP, but I read their question precisely as it was written. > The global eggs() returns the value from calling spam() and should use > the *global* spam. The eggs in namespace Shop calls spam and returns > its value, and I'd expect that call to resolve to Shop.spam, using the > namespace eggs is defined in. If that's not how you imagine namespaces > working, I think they are going to be quite non-intuitive for at least > a certain set of users (including me...) > > Paul > ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/7S3QSLGIL3HTDD2FK4P6WQUI32BY4A3E/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Namespaces!
Whoops. I totally misread that! My brain unhelpfully supplied string quotes in the return statement of the `eggs` methods, rather than parsing them as function calls. ...for some reason I could not explain to you. Maybe I've grown too dependent on syntax highlighting! I see what Steven meant now. Ignore what I typed earlier, then. To be honest, I do completely agree. I think the most useful and least surprising implementation would be to give the namespace block its own temporary scope (with outer names still available), and then only at the end of the block just before the scope is destroyed do any names bound to it get set on the parent scope. So: def spam(): return "spam spam spam!" def eggs(): return spam() namespace Shop: old_spam = spam # No NameError, the `spam` from module scope is still accessible here if we want it! def spam(): return "There's not much call for spam here." new_spam = spam # this now refers to the function defined immediately above def eggs(): return spam() # this refers to the same object as `new_spam`, not the `spam` from globals() # at this point globals()['Shop.spam'] would still raise a NameError. It doesn't exist yet! namespace Shelf: this_is_shop_spam = spam # However, we can access it from inside another nested namespace as a simple name. The scoping rules on nested classes would not allow this! # at this point globals()['Shop.spam'] exists! Sorry Steven! I totally misunderstood your example. It was a really good point. Thanks :) On Wed, May 5, 2021 at 12:06 PM Paul Moore wrote: > On Wed, 5 May 2021 at 11:33, Matt del Valle wrote: > > >> To give an example: > >> > >> def spam(): > >> return "spam spam spam!" > >> > >> def eggs(): > >> return spam() > >> > >> namespace Shop: > >> def spam(): > >> return "There's not much call for spam here." > >> def eggs(): > >> return spam() > >> > >> print(eggs()) > >> # should print "spam spam spam!" > >> print(Shop.eggs()) > >> # should print "There's not much call for spam here." > > > > > > I'm guessing this was a typo and you meant to type: > > > > print(spam()) > > # should print "spam spam spam!" > > print(Shop.spam()) > > # should print "There's not much call for spam here." > > > > Because if you did, then this is precisely how it would work under this > proposal. :) > > I'm not the OP, but I read their question precisely as it was written. > The global eggs() returns the value from calling spam() and should use > the *global* spam. The eggs in namespace Shop calls spam and returns > its value, and I'd expect that call to resolve to Shop.spam, using the > namespace eggs is defined in. If that's not how you imagine namespaces > working, I think they are going to be quite non-intuitive for at least > a certain set of users (including me...) > > Paul > ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/JOPSMGLXNWQTN6RXB6CEDOAAARDU23PI/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Namespaces!
On Wed, 5 May 2021 at 11:33, Matt del Valle wrote: >> To give an example: >> >> def spam(): >> return "spam spam spam!" >> >> def eggs(): >> return spam() >> >> namespace Shop: >> def spam(): >> return "There's not much call for spam here." >> def eggs(): >> return spam() >> >> print(eggs()) >> # should print "spam spam spam!" >> print(Shop.eggs()) >> # should print "There's not much call for spam here." > > > I'm guessing this was a typo and you meant to type: > > print(spam()) > # should print "spam spam spam!" > print(Shop.spam()) > # should print "There's not much call for spam here." > > Because if you did, then this is precisely how it would work under this > proposal. :) I'm not the OP, but I read their question precisely as it was written. The global eggs() returns the value from calling spam() and should use the *global* spam. The eggs in namespace Shop calls spam and returns its value, and I'd expect that call to resolve to Shop.spam, using the namespace eggs is defined in. If that's not how you imagine namespaces working, I think they are going to be quite non-intuitive for at least a certain set of users (including me...) Paul ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/SCBZDQQT3A3OISOTSOB7WSQNI5HFHSBL/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Namespaces!
On Wed, May 5, 2021 at 8:33 PM Matt del Valle wrote: > Creating lots of unnecessary classes just for namespacing, as we currently > have to resort to, isn't ideal. > > What you're calling 'an unnecessary level of indirection', quickly becomes a > big boost to clarity (both in the written code and when using said code in an > IDE) in more complex situations. Ask yourself why library authors namespace > out the API of their library across multiple modules/packages. It's the same > reason. > I absolutely agree that creating lots of classes just for namespacing is unideal. Where we disagree is where the problem is. You think the problem is in the "creating lots of classes". I think the problem is in "needing that much namespacing" :) That's another reason to go looking for *real* examples. Every example given in this thread can be dismissed for being too simple, while simultaneously being defended as "just an example". Three levels of namespacing just to find one leg out of eight is a complete waste of effort. So find us some better examples to discuss, examples that really support your proposal. These ones, as mentioned, are great for explaining/discussing what it does, but not for explaining why it needs to be done. ChrisA ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/S6ZRZQO6MKGAYRGYHBKLLMKIAN4L6AOO/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Namespaces!
> > So if A is capable of looking up "B.C.D", but it's also capable of > looking up "B" and following the chain... what happens when you > reassign something? What does this line of code do? > A is capable of looking up B.C.D in one step if you use `getattr` because the way A forwards on attribute lookups is roughly equivalent to (copy-pasting this from an earlier post): class NamespaceProxy: ... def __getattr__(self, name): return getattr(self.__parent_scope__, f"{self.__namespace_name__}.{name}") def __setattr__(self, name, value): setattr(self.__parent_scope__, f"{self.__namespace_name__}.{name}", value) So it would concatenate its own name ("A") with a dot with the name being looked up ("B.C.D") and then serve up globals()['A.B.C.D'], which is the key under which the value of D is stored. It can also follow the chain because: >>>globals()['A'] of > >>>globals()['A.B'] of > >>>globals()['A.B.C'] of > These also exist in the module globals(), (they were set there with those names in the `namespace` statement). A chained lookup just involves looking these namespace objects up one-by-one in the globals(). >>> A.B.C.D = "spam" > > Does it change what getattr(A, "B.C.D") returns? > Yes, it would, because it is no different to just explicitly setting: globals()[''A.B.C.D'] = "spam" That's not why ideas get dismissed out of hand. Onus is not on the > status quo to prove itself; onus is on the proposal to show its value. > If you want your idea to be taken seriously, you have to demonstrate > that it would give some sort of real improvement. > I get this, I do. And you're not wrong. I guess what I'm trying to say is that there's a lot to be said for being kind. I've seen several instances of people coming here with a new idea and sort-of cringed sympathetically at the kind of response they've gotten. I can just imagine someone relatively new to python getting really puppy-dog excited because they think they've got something worthwhile to contribute (without understanding why it may not work) and jumping through a few hoops to get onto this list only to be practically yelled out of the room by cranky old developers. What a horribly demoralizing experience that must be! There are some people who genuinely act like it is a personal attack on them when someone else comes along to discuss their shiny new idea on a list intended for... discussing potential new language ideas. I don't think that reflects on our community very well to newcomers. It costs us nothing to be kind, even if you *do* have to say something another person might not like to hear. There are ways to soften it and be informational rather than rude. Especially in a medium like this where tone doesn't carry and it's easy to misconstrue something as harsher than the person meant it. Even little things like your smiley face earlier: Precisely. :) > Go a shockingly long way towards conveying that we're on the same page having a discussion to try and improve python together, rather than an ego-fuelled shouting match. That's not the same, though. Binary operators are NOT syntactic sugar > for method calls - they do a number of checks that allow for reflected > methods and such. > Fair enough, I just used the first example that came to mind, which in this case was wrong. My point was more about syntactic sugar in general. > To give an example: > > def spam(): > return "spam spam spam!" > > def eggs(): > return spam() > > namespace Shop: > def spam(): > return "There's not much call for spam here." > def eggs(): > return spam() > > print(eggs()) > # should print "spam spam spam!" > print(Shop.eggs()) > # should print "There's not much call for spam here." > I'm guessing this was a typo and you meant to type: print(spam()) # should print "spam spam spam!" print(Shop.spam()) # should print "There's not much call for spam here." Because if you did, then this is precisely how it *would* work under this proposal. :) In the module globals() you would have the first version of `spam` under the key 'spam', and the second one under 'Shop.spam', which is the object that the attribute lookup `Shop.spam` would return If we have a namespace concept, it should actually be a namespace, not > an weird compiler directive to bind names in the surrounding global > scope. > This is an implementation detail that the end-user would basically not need to worry about except when iterating dynamically over the globals()/class __dict__/object __dict__. But that's the entire point. `namespace` is intended to build namespaces within some scope, not to create whole new scopes. If you wanted a new scope you could create a new class/object/module. > For example, you could rewrite this: > > > > class Legs: > > def __init__(self, left, right): > > self.left, self.right = left, right > > > > > > class Biped: > > def