[Python-ideas] Re: s?scanf [was: A string function idea]
On Wed, 30 Mar 2022 at 15:11, Stephen J. Turnbull wrote: > > Chris Angelico writes: > > > [fruit] = sscanf(sample, "%*sfruit:%s\n") > > I'm warming to this idea. It does hit the sweet spot of doing exactly > what you want -- except when it can't do what you want at all. :-) > It's concise and quite powerful, applicable to many common use cases. It fits nicely between "x,sep,y = str.partition(...)" and a regular expression. > I do have one windowframe of the bikeshed to paint: this is Python, so > maybe just "scanf" is a fine name? Sure, whether it's scanf or sscanf doesn't really matter to me. And - I had to look this up - the converse is referred to in the docs as "printf-style formatting", not sprintf. So that's an argument in favour of "scanf". > The first argument can be any > iterable of characters, and if an iterator it would leave the > iteration pointer where it left off (eg, beginning of next line in > 'sample' above). Hmm, I'm not really a fan. To be efficient, scanf will need to be able to use core string searching functionality - str.index() is faster than simply iterating over a string and comparing character by character. I don't think, for instance, that json.load() promises anything about where it leaves an iterable; in fact, I believe it simply reads everything into a string and then parses that. It would be worth supporting both byte strings and text strings, though, for the same reason that they both support printf formatting. 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/5LHEYKCKVIYHEVCBVVEZDCWCZ4SCZKRX/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] s?scanf [was: A string function idea]
Chris Angelico writes: > [fruit] = sscanf(sample, "%*sfruit:%s\n") I'm warming to this idea. It does hit the sweet spot of doing exactly what you want -- except when it can't do what you want at all. :-) It's concise and quite powerful, applicable to many common use cases. I do have one windowframe of the bikeshed to paint: this is Python, so maybe just "scanf" is a fine name? The first argument can be any iterable of characters, and if an iterator it would leave the iteration pointer where it left off (eg, beginning of next line in 'sample' above). Then the question would be how to use that feature. Specifically, how does scanf deal with the case that the parse fails? Consider while True: fruits.append(scanf(input_file, "%*sfruit:%s\n")[0]) Neither returning a sentinel (presumably None) nor raising a NotFound exception seems palatable. Can it raise StopIteration, perhaps conditional on the first argument having a .__next__? ___ 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/HP2FSLOKABQM7HS2ZGKVSRVAI7SSIQYW/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: A string function idea
On Tue, Mar 29, 2022 at 4:08 PM Steven D'Aprano wrote: > I have no strong opinion on whether this simple function should be built > into the string class, I do -- this is not sufficiently general to be a string method. > but I do have a strong opinion about re-writing > it into a slower, more fragile, harder to understand, less user-friendly > regex. > I do agree there. I also agree with Chris A's suggestion: *some* scanner / parser that could be used for this and many other things that's significantly more straightforward that regex's. -CHB -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ 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/LOHHZQD2ZPAZL52OLOWIB5IBCFQQH6KN/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: A string function idea
On Wed, 30 Mar 2022 at 10:08, Steven D'Aprano wrote: > Here's the version of grab I used: > > def grab(text, start, end): > a = text.index(start) > b = text.index(end, a+len(start)) > return text[a+len(start):b] > This is where Python would benefit from an sscanf-style parser. Instead of regexps, something this simple could be written like this: [fruit] = sscanf(sample, "%*sfruit:%s\n") It's simple left-to-right tokenization, so it's faster than a regex (due to the lack of backtracking). It's approximately as clear, and doesn't require playing with the index and remembering to skip len(start). That said, though - I do think the OP's task is better served by a tokenization pass that transforms the string into something easier to look things up in. 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/U4BFSBS5EAD7QNBMHZXOXYMBQVMNXCFB/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: A string function idea
On Tue, Mar 29, 2022 at 11:00:41AM +0300, Serhiy Storchaka wrote: > 28.03.22 15:13, StrikerOmega пише: > >And I want to grab some kind of value from it. > > There is a powerful tool designed for solving such problems. Is is > called regular expressions. > > >sample.grab(start="fruit:", end="\n") > > >> 'apple' > > re.search(r'fruit:(.*?)\n', sample)[1] Now do grab(start="*", end="."). Of course you know how to do it, but a naive solution: re.search(r'*(.*?).', sample)[1] will fail. So now we have to learn about escaping characters in order to do a simple find-and-extract. And you need to memorise what characters have to be escaped, and if your start and end parameters are expressions or parameters rather than literals, the complexity goes up a lot: # Untested, so probably wrong. re.search(re.escape(start) + "(.*?)" + re.escape(end))[1] and we both know that many people won't bother with the escapes until they get bitten by bugs in their production code. And even then, regexes are a leading source of serious software vulnerabilities. https://cwe.mitre.org/data/definitions/185.html Yes, regular expressions can be used. We know that regexes can be used to solve most problems, for some definition of "solve". Including finding prime numbers: https://iluxonchik.github.io/regular-expression-check-if-number-is-prime/ A method can raise a useful, self-explanatory error message on failure. Your regex raises "TypeError: 'NoneType' object is not subscriptable". A method can be written to parse nested brackets correctly. A regular expression cannot. And then regexes are significantly slower: >>> sample = 'Hello world fruit: apple\n' >>> setup = "from __main__ import grab, sample; import re" >>> t_grab = Timer("grab(sample, 'fruit', '\\n')", setup=setup) >>> t_regex = Timer("re.search(r'fruit:(.*?)\\n', sample)[1]", setup=setup) >>> min(t_grab.repeat()) 0.47571489959955215 >>> min(t_regex.repeat()) 0.8434272557497025 Here's the version of grab I used: def grab(text, start, end): a = text.index(start) b = text.index(end, a+len(start)) return text[a+len(start):b] I have no strong opinion on whether this simple function should be built into the string class, but I do have a strong opinion about re-writing it into a slower, more fragile, harder to understand, less user-friendly regex. Don't make me quote Jamie Zawinski again. -- 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/HB34UPEP7B3S5O76KEL3B5GN5TB4ODCJ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Anonymous namedtuples, revisited
On 3/29/22 14:41, Christopher Barker wrote: > Ethan Furman queried: >> The `__dict__` is needed to store the field names -- did you add `__dict__` to the >> `__slots__`? > > Nope — though the error indicated that I couldn’t add anything to __slots__ when subclassing tuple. But I may have > misunderstood the error. Ah, that's right -- it's saying that *instances* cannot have anything in `__slots__`, but the class can still have fields: >>> class Tuple(tuple): ... this = 'eggs' ... that = 'spam' ... __slots__ = () ... def __new__(cls, *args): ... return tuple.__new__(cls, *args) ... >>> t = Tuple((1,)) >>> t (1,) >>> t.this 'eggs' >>> t.that 'spam' So the Tuple class would have properties that redirect to the correct offset -- but that would require a different tuple class for each field configuration. -- ~Ethan~ ___ 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/IHOJQLM5KZIKC6TNKZCYHQ25MICBIIW5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: A string function idea
On Tue, Mar 29, 2022 at 12:35:56AM -0700, Paul Bryan wrote: > I wonder if applying regular expressions would sufficiently address > your use case. 'Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.' -- Jamie Zawinski Apart from (probably) being slower and harder to understand, what benefit would a regular expression bring to this problem? Julio already has a working solution that does exactly what he wants: > > I have implemented this function locally to use it for my personal > > projects and It has proven to be really useful in practice, so I hope > > you find it useful as well and consider adding it as a class method > > for strings in Python. -- 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/MCIOI2RB24NOHVGF7IFQDXPJILLSKEAW/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: A string function idea
On Tue, Mar 29, 2022 at 09:12:36AM +0200, StrikerOmega wrote: > The grab function would find the index of the first occurrence of the > "start" string in the parent string and then the next occurrence of the > "end" string starting from that index and return the substring between > those. That's what I guessed it would do. So your earlier statement: "You can also "grab" values enclosed in brackets or in any kind of character and It works as you would expect." is wrong. When using brackets I expect it to understand nesting. -- 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/OY3QBRRJVRRB3SWS54CRUFA2O6QA22X5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Anonymous namedtuples, revisited
> >> The `__dict__` is needed to store the field names -- did you add > `__dict__` to the > >> `__slots__`? Nope — though the error indicated that I couldn’t add anything to __slots__ when subclassing tuple. But I may have misunderstood the error. Also, frankly, I’m completely confused by __slots__ : looking at the namedtuple implementation, it sets slots to an empty tuple. But it does have instance attributes without a __dict__. > Maybe I'm being an ignoramus but: how would it be possible to even use > slots? Slots > > are descriptors living in the class namespace. You don't know ahead of > time what the > > member names are, so you can't use slots, right? The idea there is that you’d store the field names in a slot, and dynamically return the values in __getattr__. In that case, frozen dict would be nice :-) Anyway — good idea? I don’t know, ‘cause I did get it to work :-) -CHB > You can use them, just make sure one of the slots is `__dict__`. > > Of course, by adding `__dict__` you lose most (all?) of the advantages of > using `__slots__` in the first place. > > -- > ~Ethan~ > ___ > 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/QM7MIHKP2GSBN6TYMPDIFKGHGC7KEH6E/ > Code of Conduct: http://python.org/psf/codeofconduct/ > -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ 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/JHPTA3REQEUTRNZWBLDYRC2MEWKWDL6C/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
Alright everyone. First of all, thanks for all your answers, I really appreciate the discussion we're having. Turns out i won't have so much free time tonight, and probably tomorrow night either, so i won't be able to answer the last few comments before some then. I apologise if i'm missing some of your answers, if you feel like i missed your post, feel free to reiterate your questions / remarks So, i wanna take that opportunity to step back just a moment, and "list out" everything i need to do in the next answer. 1) I've been requested to provide "real life" examples of code, I'll try to provide it 2) I think I failed at explaining my idea clearly enough, there are points that i wanna make more clear, and overall, I think it would be nice to provide a "round 2" of my idea, improved by all your remarks, and made more explicit where it was unclear. This is probably gonna be a very lenghty post, and i apologise for that in advance. I started a draft here if you are curious : https://github.com/malmiteria/super-alternative-to-super/blob/master/conversation/README.md. When ready, i'll copy paste it here, but i'll leave it up on that link. 3) I'm also thinking about adding personas to the mix, so we can discuss in more depths how this proposal would affect the overall community. (I think that's a valuable exercice to do at least once to check if a solution we would come up with would be a fit for everyone) so far, i can think of : - 'the scientist' : he doesn't care about the langage much, he just needs a tool for work, and it happens to be python - 'the web dev' : he doesn't necesserly know the langage in depths, do not need to implement the perfect solution, but is still fairly knowledgable - 'the lib maker' : he's very knowledgable, has to think of it's users as varying in knowledge and skill, can't let responsibility of his lib leap into the lib client hands - 'the tester' : wanna test everything - 'the refactorer' : hates all code smells If you think i'm missing important persona that would constitute a decent chunk of the python user community, please feel free to add them to the list. 4) I think it is sometimes unclear when i'm talking about how things are rn, how things should be, how i imagine things in my solution, and so on. I'll try to be expllicit about the full context of my statements in the future 5) I'll try to explicit the assumption i work under. Those are sometime hard to detect for me, I do not always realise what it is i consider obvious, when it might not be so obvious in fact. I'm sure i'll have more to explicit in the future. I think that's it. I'll also try to take some time to read the link you shared and i didn't know about, but i don't wanna leave you hanging for too long either, so I might read it this weekend. If you have any question about things that you want me to make more explicit, point that you think i might have forgotten, or anything you wanna make me aware of, please keep posting it here, i'll be reading it when i can get more free time. ___ 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/OLATMNG5R4WFMSVIGAJYVSER6AKSEFFT/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Anonymous namedtuples, revisited
On 3/29/22 09:57, Ricky Teachey wrote: > On Tue, Mar 29, 2022 at 12:49 PM Ethan Furman wrote: >> The `__dict__` is needed to store the field names -- did you add `__dict__` to the >> `__slots__`? (Of course, if you've added `__dict__` then you lose the limited size >> of `__slots__`.) > > Maybe I'm being an ignoramus but: how would it be possible to even use slots? Slots > are descriptors living in the class namespace. You don't know ahead of time what the > member names are, so you can't use slots, right? You can use them, just make sure one of the slots is `__dict__`. Of course, by adding `__dict__` you lose most (all?) of the advantages of using `__slots__` in the first place. -- ~Ethan~ ___ 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/QM7MIHKP2GSBN6TYMPDIFKGHGC7KEH6E/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Anonymous namedtuples, revisited
On Tue, Mar 29, 2022 at 12:49 PM Ethan Furman wrote: > On 3/29/22 09:14, Christopher Barker wrote: > > > [...] I tried to use __slots__ in TupleWithNames, but apparently you > can't use __slots__ in a > > tuple subclass ('cause tuple's already using it ??) -- but that could > be done in a builtin. > > then it wouldn't need a __dict__ > > The `__dict__` is needed to store the field names -- did you add > `__dict__` to the `__slots__`? (Of course, if you've > added `__dict__` then you lose the limited size of `__slots__`.) > > -- > ~Ethan~ > Maybe I'm being an ignoramus but: how would it be possible to even use slots? Slots are descriptors living in the class namespace. You don't know ahead of time what the member names are, so you can't use slots, right? Unless you modify the TupleWithNames class on the fly, adding slot names as they are needed. But then you need some kind of machinery for each instance to know which slots are valid for that instance, and to block access to slots that aren't part of that instance. Again, I might just be a doof. --- Ricky. "I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler ___ 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/GPDPVTWALPF63QBD4BPSAXA2VTQOTIIJ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Anonymous namedtuples, revisited
On 3/29/22 09:14, Christopher Barker wrote: > [...] I tried to use __slots__ in TupleWithNames, but apparently you can't use __slots__ in a > tuple subclass ('cause tuple's already using it ??) -- but that could be done in a builtin. > then it wouldn't need a __dict__ The `__dict__` is needed to store the field names -- did you add `__dict__` to the `__slots__`? (Of course, if you've added `__dict__` then you lose the limited size of `__slots__`.) -- ~Ethan~ ___ 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/B3JZKXQ4HDW5IRNMYKDKB5QFGHRR42AH/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Anonymous namedtuples, revisited
On Tue, Mar 29, 2022 at 6:37 AM Joseph Martinot-Lagarde < contreba...@gmail.com> wrote: > Both suggested implementations are very interesting. If I'm not wrong they > have exactly the same behavior (except for __dict__). > pretty close, yes -- probably differences with pickling, and if you did an type checking, very different. Performance-wise with a quick test I get the following results: > > t = (1, 2) > print("sizeof", sys.getsizeof(t)) # 56 > print("sizeof type", sys.getsizeof(type(t))) # 408 > print(timeit.timeit("(1, 2)")) # ~0.01 > > nt = namedtuple("nt", ["x", "y"]) > print("sizeof", sys.getsizeof(nt(1, 2))) # 56 > print("sizeof type", sys.getsizeof(type(nt(1, 2 # 896 > print(timeit.timeit("nt(1, 2)", setup="from __main__ import nt")) # ~0.2 > > pt = atuple(x=1, y=2) > print("sizeof", sys.getsizeof(pt)) # 56 > print("sizeof type", sys.getsizeof(type(pt))) # 896 > print(timeit.timeit("atuple(x=12, y=16)", setup="from __main__ import > atuple")) # ~0.8 > > point = TupleWithNames(x=1, y=2) > print("sizeof", sys.getsizeof(point)) # 64 > print("sizeof type", sys.getsizeof(type(point))) # 1064 > print(timeit.timeit("TupleWithNames(x=12, y=16)", setup="from __main__ > import TupleWithNames")) # ~0.8 > you have to be careful with getsizeof() -- I don't think it digs into nested objects. Anyway, it would certainly require a close look. The timing performance of both solutions is roughly the same given the > measurament variation, That surprises me -- a tuple has to call namedtuple, and there's a lot of work done in there -- very odd. I guess that's why we have to profile, but I'd still give that a closer look. > but way slower than tuple an namedtuple. > well, with namedtuple, you aren't taking into account the creation of the class -- so if you make thousands of the same one, yes, but if you make only a couple, then not so much. > TupleWithNames is a bit more memory hungry than atuple and namedtuple, but > there is only one type so if I understand correctly it would be a win for > multiple instances. > I think so -- at least of atuple -- though one could create a cache of namedtuples so that atuple would reuse an existing one if was already there. Maybe there is room for optimisation in both cases ? > I"m sure -- namedtuple use sys.intern on the names, that would help. and I tried to use __slots__ in TupleWithNames (sorry for that horrible name ;-) ), but apparently you can't use __slots__ in a tuple subclass ('cause tuple's already using it ??) -- but that could be done in a builtin. then it wouldn't need a __dict__ There's also various options for storing the fields -- I only tried the first one I thought of. This reminds me -- it would be kinda cool if there was an easier, more robust way to make an immutable in Python -- maybe a frozendict for __dict__? Anyway, if someone wants to take this further, I'd be glad to help. -CHB -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ 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/OHM6KLGJSQUNP7VBXBCFCHRUONJ6MS67/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: A string function idea
Thanks for teaching me about the __getitem__ method of the Match class. I always do .group(1) before. Abdulla Sent from my iPhone > On 29 Mar 2022, at 12:02 PM, Serhiy Storchaka wrote: > > re.search(r'fruit:(.*?)\n', sample)[1] ___ 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/PM3DNWEP4NFXT25GPHGP4I4J6YFKQNVZ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
malmiteria writes: > class An: > def method(self): > print('An') > class A[n-1](An): pass > ... > class A1(A2): pass > class A0(A1): > def method(self): > self.__as_parent__(An).method() > > A0().method() prints 'An' Of course it prints 'An', and so does class A00(A1): def method(self): super(A[n-1], self).method() A00().method() Equally of course, __as_parent__(An) is exactly what I mean by "arbitrarily deep". Note that all you need to identify A[n-1] in this case is its class definition, and that's probably the great majority of cases. To find out, all you need to do is type >>> class A00(A1): pass ... >>> A00.__mro__ [A00, A1, ..., A[n-1], An] so it's not hard to figure this out. > > (a) there are > > people who use it for more advanced purposes and (b) it can't cause you > > any confusion in that case. > > (a) What are those more advanced feature? On top of the classic > inheritance features, I can only think of dependency injection > in the inheritance tree. Yes, that's precisely what I have in mind. However, the application is declarative composition (I think I just invented that name), as "Python's super() considered super" demonstrates with the trivial class LoggingOD[1]. This is very powerful and expressive (when it works). At this time, it seems like C3 provides the largest set of cases where it works. > Such a feature could be replaced, although i didn't provide a > replacment for this feature, it doesn't seem like it's gonna be > hard to do, __as_parent__ could rely on a dict, which would hold as > key a class, and as value a class too. If the targeted class is in > the keys, target the corresponding value instead. This class could > then inherit from the class it replaced, and you got your > dependency injection. Have you read "Python's super() considered super!"? I definitely get the impression that you have not understood it. The point of several of the examples is that by using super() you can allow a future subclass to insert a method implementation in the MRO without knowing either the future subclass nor the class that currently implements the method. There are constraints on it, but the MRO allows you to express many such dependencies in a straightforward declarative manner, whereas your dict implementation is going to require a lot of explicit plumbing in derived classes. Also, the MRO approach allows different classes to inject different methods, but you're going to need something more complicated than the simple class -> class mapping. > On top of that, it unties a lot more this dependency injection > feature from the method resolution algorithm. You write that like you think that's a good thing, or it's not already possible to do that. ;-) > (b) Wrong! The common use case for inheritance and super is what > informs most people of its behavior, I think that's irrelevant, since the most common case is single inheritance, and there's only one (sane) way to resolve methods in that case. Trying to extrapolate from that to behavior in a multiple inheritance context simply means you haven't thought about multiple inheritance. > My alternative doesn't do those jumps, and i think overall matches > more closely what an untrained mind [...] would expect. I think that's probably the worst possible criterion for systems design. "Principle of Least Astonishment", sure, but at some point you want your systems to have some power. In theory any 3rd grader could fly a plane with a Wii handset, but maybe it's a better idea to employ a trained pilot. > > But C3/super assumes nothing of the kind. > > At first i was gonna answer that it of course does make this > assumption, but I think we aren't exactly talking about the same > thing. > I was saying that the assumption that it can make sense to order > class inheritance trees C3/super doesn't *assume* it makes sense. It proposes it, and then demonstrates that it satisfies the useful and intuitive properties of local precedence ordering and monotonicity. Experience shows it *obviously* *does* make sense in many cases, in particular with single inheritance. But there are also many cases where it makes sense with multiple inheritance. > which it turns out can't solve all scenarios. I think this proves > that this assumption was wrong. But the assumption that something needs to solve all scenarios to be useful and usable is *your* assumption, which is clearly *wrong*. > So overall, i think we agree on the matter of fact of today's C3 > behavior, and overall, i think we agree that C3 is an incomplete > solution? Yes. Who cares? > The solution i propose would be able to cover those cases C3 > doesn't. Because it wasn't build around the idea of ordering. Sure, but it gives up on many useful cases of declarative composition, basically limiting it to sets of mixins with disjoint attribute sets. And in any case, super() also covers those
[Python-ideas] Re: Anonymous namedtuples, revisited
@Michael: As the previous author I fully support this proposal! ;) Thank you for the revival. For reference, since you linked one of the answer of the original thread, this is my original proposal: https://mail.python.org/pipermail/python-ideas/2016-April/039836.html Both suggested implementations are very interesting. If I'm not wrong they have exactly the same behavior (except for __dict__). Performance-wise with a quick test I get the following results: t = (1, 2) print("sizeof", sys.getsizeof(t)) # 56 print("sizeof type", sys.getsizeof(type(t))) # 408 print(timeit.timeit("(1, 2)")) # ~0.01 nt = namedtuple("nt", ["x", "y"]) print("sizeof", sys.getsizeof(nt(1, 2))) # 56 print("sizeof type", sys.getsizeof(type(nt(1, 2 # 896 print(timeit.timeit("nt(1, 2)", setup="from __main__ import nt")) # ~0.2 pt = atuple(x=1, y=2) print("sizeof", sys.getsizeof(pt)) # 56 print("sizeof type", sys.getsizeof(type(pt))) # 896 print(timeit.timeit("atuple(x=12, y=16)", setup="from __main__ import atuple")) # ~0.8 point = TupleWithNames(x=1, y=2) print("sizeof", sys.getsizeof(point)) # 64 print("sizeof type", sys.getsizeof(type(point))) # 1064 print(timeit.timeit("TupleWithNames(x=12, y=16)", setup="from __main__ import TupleWithNames")) # ~0.8 The timing performance of both solutions is roughly the same given the measurament variation, but way slower than tuple an namedtuple. TupleWithNames is a bit more memory hungry than atuple and namedtuple, but there is only one type so if I understand correctly it would be a win for multiple instances. Maybe there is room for optimisation in both cases ? ___ 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/YKTIWCHLNUONTVCXU3C26CJ5VTB6L2OH/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Anonymous namedtuples, revisited
On Fri, Mar 25, 2022 at 12:17 AM Brendan Barnwell wrote: > On 2022-03-24 10:43, Andrew Svetlov wrote: > > The proposal doesn't work well with type hints: atuple(a=1, b=2) and > > atuple(a="a", b="b") generates the same type. > > I'm neither here nor there on the original proposal, but I just > want to > push back against this reasoning. Type hints are an entirely optional > feature of Python which do not affect the runtime behavior of Python > code in any way (except insofar as other code explicitly reads the > annotations), and this has been explicitly reiterated multiple times > (e.g., in PEPs). In my view, how something interacts with typing has no > relevance in evaluating a proposal such as this. To allow typing > considerations to constrain Python's future development in any way > whatsoever is to slide down the slippery slope which was explicitly > disavowed in PEP 484, namely a gradual move towards a de facto > "requirement" for static typing. I would most heartily prefer to avoid > that. > > strong +1 > -- > Brendan Barnwell > "Do not follow where the path may lead. Go, instead, where there is no > path, and leave a trail." > --author unknown > ___ > 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/L67XX3TUEOFNLL4EJ56SX4UQAAV3TOU5/ > 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/5TFHEWOGACIWV5N5CGI64UAELCXVUIUQ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Anonymous namedtuples, revisited
I think I'd often reach for an optimized version of something like this over SimpleNamespace or even a Dataclass if it existed. On Tue, Mar 29, 2022, 2:04 AM Christopher Barker wrote: > Finally got around to fleshing out my idea here. > > My thought was to make an anonymous names tuple not as a new anonymous > class, but simply as an instance with specific field names. So all of these > would the the same class, but they would also be lightweight, and all > subclasses of tuple -- from a typing perspective, it's just be a tuple - > and could be used anywhere a tuple could. > > Here's a quick prototype I came up with: > > class TupleWithNames(tuple): > def __new__(cls, **fields): > self = tuple.__new__(cls, fields.values()) > for name, val in fields.items(): > self.__dict__[name] = val > return self > > def __setattr__(self, attr, val): > raise AttributeError("Can't set attributes on TupleWithNames") > > def __repr__(self): > return f"TupleWithNames({', '.join(f'{k}={v}' for k, v in > self.__dict__.items())})" > In [172]: point = TupleWithNames(x=5, y=10) > > In [173]: point > Out[173]: TupleWithNames(x=5, y=10) > > In [174]: point.x > Out[174]: 5 > > In [175]: point.y > Out[175]: 10 > > In [176]: point.x = 2 > --- > AttributeErrorTraceback (most recent call last) > in > > 1 point.x = 2 > > ~/PythonStuff/tuplewithnames/tuplewithnames.py in __setattr__(self, attr, > val) > 11 > 12 def __setattr__(self, attr, val): > ---> 13 raise AttributeError("Can't set attributes on > TupleWithNames") > 14 > 15 def __repr__(self): > > AttributeError: Can't set attributes on TupleWithNames > > In [177]: point.z = 3 > --- > AttributeErrorTraceback (most recent call last) > in > > 1 point.z = 3 > > ~/PythonStuff/tuplewithnames/tuplewithnames.py in __setattr__(self, attr, > val) > 11 > 12 def __setattr__(self, attr, val): > ---> 13 raise AttributeError("Can't set attributes on > TupleWithNames") > 14 > 15 def __repr__(self): > > AttributeError: Can't set attributes on TupleWithNames > > In [178]: point[0] > Out[178]: 5 > > In [179]: point[1] > Out[179]: 10 > > In [180]: point[1] = 3 > --- > TypeError Traceback (most recent call last) > in > > 1 point[1] = 3 > > TypeError: 'TupleWithNames' object does not support item assignment > > So it's a (subclass of) tuple -- you can access the entries by name, you > can't change them. > > It's truly immutable, 'cause the __dict __ is there to mess with, but that > (I think) could be fixed if it were implemented in C. > > This really simple version hashes as the tuple -- so it's the same as a > tuple with the same values, or a TupleWithNames with the same values, and > any arbitrary names. > > Which I think is OK -- the idea here is that it IS just like a tuple > except you can use the field names to access items for readability. But you > could customize the hash, too if you wanted. > > Anyway -- that's in idea -- details to be fleshed out if anyone wanted to > pursue this. > > -CHB > > > > > On Sat, Mar 26, 2022 at 1:49 PM Christopher Barker > wrote: > >> >> If I wanted to submit this as a pep (or even just submit this for a >>> potential sponsorship), is the best way to go about it to work directly in >>> a clone of the c/python repo, or to write a standalone library first and >>> then after preliminary approval, add it to c/python? >> >> >> You don’t need an implementation to write a PEP, and certainly not to get >> a sponsor. >> >> That being said, a prototype can be helpful to work out the issues. >> >> You could go either way, but if it can be stand-alone, that’s easier, >> especially for others to try it out. >> >> -CHB >> >> >>> ___ >>> 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/Q6JTO37I42OKOAIJVBD63UL5QO3KEYLI/ >>> Code of Conduct: http://python.org/psf/codeofconduct/ >>> >> -- >> Christopher Barker, PhD (Chris) >> >> Python Language Consulting >> - Teaching >> - Scientific Software Development >> - Desktop GUI and Web Development >> - wxPython, numpy, scipy, Cython >> > > > -- > Christopher Barker, PhD (Chris) > > Python Language Consulting > - Teaching > - Scientific Software Development > - Desktop GUI and Web Development > - wxPython, numpy, scipy, Cython > ___ > Python-ideas mailin
[Python-ideas] Re: mro and super don't feel so pythonic
On Tue, 29 Mar 2022 at 21:34, Steven D'Aprano wrote: > > On Tue, Mar 29, 2022 at 06:23:06AM +1100, Chris Angelico wrote: > > > If I'm reading this correctly, you're defining a "conflict" as finding > > two implementations of the same-named method in independent subtrees > > of inheritance - that is, when you say "class Pizza(Crust, Topping):", > > you're treating Crust and Topping as completely independent, and if > > they both define an add_cheese method, that's a conflict. > > You've never had pizza with cheesy crust *and* cheese as a topping? That's exactly my point: I don't see this as a conflict. I *like* my pizza to have all the cheeses! > > That's not inheritance. That's composition. > > I wouldn't call it composition unless it was implemented using > composition instead of inheritance. > > I would call it a *subset* of inheritance. Hmm, my point is that, if it's considered a conflict, then this isn't really acting as inheritance. If it's inheritance, then each method is acting on *the pizza*, but if it's composition, then some methods are acting on the pizza's crust, and others are acting on the pizza's toppings. Ultimately, the difference between composition and inheritance is one of design, and there are no fundamentally wrong decisions, just decisions where you might not like the consequences. But this is why I keep asking for non-toy examples, as it's extremely hard to discuss design matters when all we have is "class C(A, B):" to go on. > That doesn't mean that cooperative MI doesn't have problems. Other > languages forbid MI altogether because of those problems, or only allow > it in a severely restricted version, or use a more primitive form of > super. MI as defined by Python is perhaps the most powerful, but also > the most potentially complicated, complex, convoluted and confusing. Agreed, all forms of MI have their problems. Python, by its nature, is guaranteed to create diamond inheritance with any form of MI (in contrast, C++ can have MI where two subbranches never intersect, which has quite different consequences); of all the ways of coping with the effects of diamond inheritance, the two I've found most useful in practice are Python's super ("go to the next one, not always up the hierarchy") and a broad idea of calling every parent (effective, but needs quite different concepts of cooperation - works well for init methods though). The term "cooperative" shouldn't put people off. I've almost never seen any form of object orientation in which it isn't at least somewhat cooperative. Some are more loosely coupled than others (IBM's SOM was an amazingly good system that allowed inheritance from other people's code, but required a complex build system), but you still have to follow protocol to make sure your class plays nicely with others. Most of the time, MI hierarchies are tightly coupled, since it's extremely difficult to negotiate anything otherwise. And honestly, I'm fine with that. 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/JESQPVJMPO74VRKIFQWKROIK2LIJJC2W/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Tue, Mar 29, 2022 at 06:23:06AM +1100, Chris Angelico wrote: > If I'm reading this correctly, you're defining a "conflict" as finding > two implementations of the same-named method in independent subtrees > of inheritance - that is, when you say "class Pizza(Crust, Topping):", > you're treating Crust and Topping as completely independent, and if > they both define an add_cheese method, that's a conflict. You've never had pizza with cheesy crust *and* cheese as a topping? > That's not inheritance. That's composition. I wouldn't call it composition unless it was implemented using composition instead of inheritance. I would call it a *subset* of inheritance. Artima is back up, so people interested in this topic **REALLY** should read what Michele Simionato has to say about it. I'm not going to apologise for dumping so many links here, I think that Michele is really onto something: OOP with inheritance is an important technique to use, but it is also widely over-sold as the solution to maintainability in large software projects and frameworks, especially when you move from single to multiple inheritance. Unfortunately, MI is just as likely to *hurt* maintainability as to help it, hence the move to composition and generics, or more restrictive forms of inheritance such as traits https://pypi.org/project/strait/ Things to know about Python super: Part 1 https://www.artima.com/weblogs/viewpost.jsp?thread=236275 Part 2 https://www.artima.com/weblogs/viewpost.jsp?thread=236278 Part 3 https://www.artima.com/weblogs/viewpost.jsp?thread=237121 Mixins considered harmful: Part 1 https://www.artima.com/weblogs/viewpost.jsp?thread=246341 Part 2 https://www.artima.com/weblogs/viewpost.jsp?thread=246483 Part 3 https://www.artima.com/weblogs/viewpost.jsp?thread=254367 Part 4 https://www.artima.com/weblogs/viewpost.jsp?thread=254507 Setting Multiple Inheritance Straight: https://www.artima.com/weblogs/viewpost.jsp?thread=246488 The wonders of cooperative inheritance, or using super in Python 3 https://www.artima.com/weblogs/viewpost.jsp?thread=281127 Multiple inheritance in Python works the way it does because it is modelling cooperative MI and the MRO and super are the Right Way to handle cooperative MI. That doesn't mean that cooperative MI doesn't have problems. Other languages forbid MI altogether because of those problems, or only allow it in a severely restricted version, or use a more primitive form of super. MI as defined by Python is perhaps the most powerful, but also the most potentially complicated, complex, convoluted and confusing. -- 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/6M7XPNKQF5IPWAK4XPJIGTKLTZBDYGK4/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: A string function idea
28.03.22 15:13, StrikerOmega пише: And I want to grab some kind of value from it. There is a powerful tool designed for solving such problems. Is is called regular expressions. sample.grab(start="fruit:", end="\n") >> 'apple' re.search(r'fruit:(.*?)\n', sample)[1] sample.grab(start="tree:[", end="]") >> 'Apple tree' re.search(r'tree:\[(.*?)\]', sample)[1] sample.grab(start="quantity:{", end="}", list_out=True) >> [5, 3] list(re.findall(r'quantity:\{(.*?)\}', sample)) ___ 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/X5EOH4P6KOWIJ3CSPWY76H6BHRDU42P5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: A string function idea
I wonder if applying regular expressions would sufficiently address your use case. On Mon, 2022-03-28 at 14:13 +0200, StrikerOmega wrote: > Hello everyone, > > When I am coding in Python I often encounter situations where I have > a string like this one. > > sample=""" > fruit:apple > tree:[Apple tree] > quantity:{5} > quantity:{3} > """ > > And I want to grab some kind of value from it. > > So let me introduce you to the grab function. This is the definition: > > def grab(start, end, list_out=False): > > Now, if you want to get the fruit from the sample string you can just > "grab" it as follows: > > sample.grab(start="fruit:", end="\n") > >> 'apple' > > You can also "grab" values enclosed in brackets or in any kind of > character and It works as you would expect. > > sample.grab(start="tree:[", end="]") > >> 'Apple tree' > > The optional argument "list_out" makes the function return a list of > values, for cases where there are several of them to grab. > > sample.grab(start="quantity:{", end="}", list_out=True) > >> [5, 3] > > The "grab" function will return only the first occurrence if > "list_out" is omitted or passed as False. > > sample.grab(start="quantity:{", end="}") > >> 5 > > sample.grab(start="quantity:{", end="}", list_out=False) > >> 5 > > As you can see, it is incredibly useful for extracting substrings > from a larger and more complex string and can change the way we parse > strings for the better. > > For example, it could simplify the way we parse the fields of HTTP > headers. It also has many applications for the parsing of > configuration files and the construction of strings for SQL queries > and bash commands among others. > > I have implemented this function locally to use it for my personal > projects and It has proven to be really useful in practice, so I hope > you find it useful as well and consider adding it as a class method > for strings in Python. > > Julio Cabria > Engineering student > Autonomous University of Madrid > ___ > 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/NV7G6W4RHTMMVIUDHQAATSVYFRIV6G7Z/ > 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/WXHJEJBB5BGI7HJJ63NPZDAV7QX6XF4G/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: A string function idea
On Tue, 29 Mar 2022 at 18:13, StrikerOmega wrote: > > The grab function would find the index of the first occurrence of the "start" > string in the parent string and then the next occurrence of the "end" string > starting from that index and return the substring between those. > This sounds like a really good job for preparsing. Take your string, parse it according to your rules, and build a list or dict of the cooked results. Then you can look up in that very easily and efficiently. Going back to the string every time tends to be inefficient, but a single pass that gives you a convenient lookup table is both easier to work with and easier to execute. In your example: sample=""" fruit:apple tree:[Apple tree] quantity:{5} quantity:{3} """ I'd start by splitting it into lines, then for each line, partitioning it on the colon, thus giving you a keyword and a value. (I'm not sure what it means to have quantity 5 and quantity 3, but I'm sure you'd define that in some way - maybe first one wins, or last one wins, or build a list of all the values, whatever makes sense.) You could end up with something like: { "fruit": "apple", "tree": "Apple tree", "quantity": ... } depending on how you resolve the conflict. Python is an excellent language for text processing; you have a wide variety of pretty cool tools available. 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/OLJRRLAGOKY74SPWEK3B47QKDUMHGEZI/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: A string function idea
The grab function would find the index of the first occurrence of the "start" string in the parent string and then the next occurrence of the "end" string starting from that index and return the substring between those. So in the example: sample = "sqrt(sin(x) + cos(y))" The grab function would return: sample.grab(start="sqrt(", end=")") >> "sin(x" This shows that "grab" is only useful given that you specify the "start" and "end" delimiters unambiguously. It depends on that to produce the correct output. Julio Cabria Engineering student Autonomous University of Madrid On Tue, Mar 29, 2022, Steven D'Aprano wrote: > On Mon, Mar 28, 2022 at 02:13:32PM +0200, StrikerOmega wrote: > >> You can also "grab" values enclosed in brackets or in any kind of character >> and It works as you would expect. >> >> sample.grab(start="tree:[", end="]") >> >> 'Apple tree' > > If we have > > sample = "sqrt(sin(x) + cos(y))" > > and sample.grab(start="sqrt(", end=")") which of these does it return? > > 1. "sin(x" > > 2. "sin(x) + cos(y)" > > > -- > 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/X7VPVCTEJ5PYGPMTNIHIG3FI73WPHIQ4/ Code of Conduct: http://python.org/psf/codeofconduct/