Re: Behaviour of pop() for dictionaries
On 14Jun2021 09:39, BlindAnagram wrote: >However, d.pop(key, [default]) returns the value (or the default) and >consistency with other pops (a good thing in my view) would suggest >that d.pop() could return a random value, which would serve my purpose >when there is only one element. If you don't care what key was popped, maybe you want a set and not a dict? Just a thought. Cheers, Cameron Simpson -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
Chris Angelico wrote at 2021-6-15 05:35 +1000: >On Tue, Jun 15, 2021 at 5:12 AM Jach Feng wrote: >> >> >>> n = [(1,2) for i in range(3)] >> >>> n >> [(1, 2), (1, 2), (1, 2)] >> >>> id(n[0]) == id(n[1]) == id(n[2]) >> True > >This is three tuples. Tuples are immutable and you get three >references to the same thing. In addition: object identity (as revealed by `id(...)`) is an implementation detail. Do not rely on it! -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
On Tue, Jun 15, 2021 at 6:32 PM Dieter Maurer wrote: > > Chris Angelico wrote at 2021-6-15 05:35 +1000: > >On Tue, Jun 15, 2021 at 5:12 AM Jach Feng wrote: > >> > >> >>> n = [(1,2) for i in range(3)] > >> >>> n > >> [(1, 2), (1, 2), (1, 2)] > >> >>> id(n[0]) == id(n[1]) == id(n[2]) > >> True > > > >This is three tuples. Tuples are immutable and you get three > >references to the same thing. > > In addition: object identity (as revealed by `id(...)`) is > an implementation detail. Do not rely on it! Hmm, not always. In this case, object identity isn't guaranteed - every literal could give you a unique object - but in other cases, object identity is a language guarantee. For instance: >>> l = (1, 2) # or [1, 2] >>> [l for _ in range(10)] [(1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2)] >>> [id(x) for x in _] [140499111503808, 140499111503808, 140499111503808, 140499111503808, 140499111503808, 140499111503808, 140499111503808, 140499111503808, 140499111503808, 140499111503808] In this example, it doesn't matter whether it's a list or a tuple (or anything else) - the IDs are all guaranteed to be the same. The only thing that's an implementation detail is whether immutable objects are folded together. You'll find similar situations with strings, numbers, etc, etc. For example, "name-like" strings are often interned in CPython, but other strings aren't, so sometimes you might find different behaviour if you have a space in the string than if you don't. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Php vs Python gui (tkinter...) for small remote database app
On Tue, Jun 15, 2021 at 08:39:51AM +1200, dn via Python-list wrote: > On 15/06/2021 07.17, Pascal B via Python-list wrote: > > Hi, > > I would like to know if for a small app for instance that requires a > > connection to a remote server database if php is more suitable than Python > > mainly regarding security. > > Php requires one port for http and one port for the connection to the > > database open. If using Python with a tkinter gui, I understand a small app > > can connect to a database so only one port to the database would need to be > > accessed/open listening to connection. So I would need to worry less about > > security if using Python over Php for something small, like a small python > > app that I give over to users. > > > > Am I missing something in this assertion? > > Yes - or maybe I'm missing the point of your question? > > There are two connections to consider: the database and the GUI. > > > Database: > [...] > > > GUI: > [...] > The (Internet-connected) world runs on TLS. If you wish to > secure/encrypt communications between application and server, this is > accepted by most. If you wish to 'secure' by reducing inter-connections, > then using tkinter and its tight-linkage to Python removes the need for > the (http) web-server. I would rather go with https-based "app", but not necessarily in PHP, if security is to be considered (albeit I am not sure if Python framework would do better). Nowadays, there should be a firewall and server sitting behind it (this is simple description, let us not put load balancing, many servers etc into the mix, or if firewall really helps). So, in case of http(s), there should be more tutorials and hints about doing this well. Browser would do the gui side, http server will talk to the database and to the world, but database itself is secured (hopefully) from outside access. I suspect it is easier to secure web server than db from various kind of 'kacks'. If you go with well rounded Python framework, you can count on its authors carefully thinking about various threats to apps written in it. Sorry, I cannot give any hints - see, I rather deteste browser based apps, so this advice goes against my own liking but one should be objective when giving advices... If you are truly new to this all, I suggest CGI, especially if you want to do some proof of concept prototype, quickly. CGI is quite easy to understand and as long as you are working out communications between your code and DB, I think it simplifies the job a lot. Later on, choose your framework and do the gui. If you go with tkinter, then you will have to do the job already done by authors of web server and web framework, you will have to rethink various problems they gave their thoughts to, but in much shorter time and on your own. -- Regards, Tomasz Rola -- ** A C programmer asked whether computer had Buddha's nature. ** ** As the answer, master did "rm -rif" on the programmer's home** ** directory. And then the C programmer became enlightened... ** ** ** ** Tomasz Rola mailto:[email protected] ** -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
Chris Angelico wrote at 2021-6-15 19:08 +1000: >On Tue, Jun 15, 2021 at 6:32 PM Dieter Maurer wrote: >> >> Chris Angelico wrote at 2021-6-15 05:35 +1000: >> >On Tue, Jun 15, 2021 at 5:12 AM Jach Feng wrote: >> >> >> >> >>> n = [(1,2) for i in range(3)] >> >> >>> n >> >> [(1, 2), (1, 2), (1, 2)] >> >> >>> id(n[0]) == id(n[1]) == id(n[2]) >> >> True >> > >> >This is three tuples. Tuples are immutable and you get three >> >references to the same thing. >> >> In addition: object identity (as revealed by `id(...)`) is >> an implementation detail. Do not rely on it! > >Hmm, not always. In this case, object identity isn't guaranteed - >every literal could give you a unique object - but in other cases, >object identity is a language guarantee. For instance: As far as I know, there are no guarantees are the language level. There are some (partially documented) implementation details for CPython (which is just one possible implementation). -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
On 15/06/21 3:18 pm, Jach Feng wrote: From a user's point, I don't really care how Python creates thoseinstances, > either using an already exist one or create a new one, as long as each element (and its sub-element) are independent from each other so a modification of one will not influence the other. The real problem is there are different methods can be used to build it and some will fail in this purpose. The * operator is one of them, but anyone else? I really like to know:-) This really has nothing to do with how the tuples are created. It all depends on what you choose to put in them. When you use square brackets to build a list, you can be sure that it will create a new list object each time. Also, if you create two tuples, by any means, containing distinct elements, you can be sure that you will get two distinct tuple objects. So, if you do this: a = [1, 2] b = [1, 2] c = [1, 2] d = [1, 2] s = (a, b) t = (c, d) then you are guaranteed to get four different list objects and two diffferent tuple objects. Does that help to ease your fears? -- Greg -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
Chris Angelico 在 2021年6月15日 星期二上午5:23:12 [UTC+8] 的信中寫道: > On Tue, Jun 15, 2021 at 7:11 AM Rob Cliffe via Python-list > wrote: > > > > This puzzled me, so I played around with it a bit (Python 3.8.3): > > > > n = [] > > for i in range(3): > > n.append((1,7,-3,None,"x")) > > for i in range(3): > > n.append((1,7,-3,None,"x")) > > print([id(x) for x in n]) > > > > a = 4 > > n = [] > > for i in range(3): > > n.append((1,7,-3,a,None,"x")) > > for i in range(3): > > n.append((1,7,-3,a,None,"x")) > > print([id(x) for x in n]) > > > > Output: > > > > [27164832, 27164832, 27164832, 27164832, 27164832, 27164832] > > [30065208, 30065496, 30237192, 30239976, 30240024, 30343928] > > > > Evidently the compiler is clever enough to pick out a constant tuple and > > create (or cause to get created) a single instance of it which is used > > when required. Indeed disassembling the code shows that LOAD_CONST is > > used to get the tuple. But it obviously can't do that when the tuple > > contains a variable. > Correct. In theory, Python could intern the tuples (as can be done > with strings), noticing that it's constructing one that is identical > to one it already has, but the effort of doing that is hard to > justify. Simpler to just build a brand new tuple every time. > > ChrisA From a user's point, I don't really care how Python creates those instances, either using an already exist one or create a new one, as long as each element (and its sub-element) are independent from each other so a modification of one will not influence the other. The real problem is there are different methods can be used to build it and some will fail in this purpose. The * operator is one of them, but anyone else? I really like to know:-) --Jach -- https://mail.python.org/mailman/listinfo/python-list
Re: Is there a way to get the following result in Python?
Am 12.06.21 um 04:02 schrieb Jach Feng: def foo(): ... # do something ... a = [] for i in range(3): ... a.append(foo()) ... a [] How about having "foo" return a list of things? Then you can append that list and return an empty list if you want nothing added: In [1]: def foo(): ...: return [1,2,3] ...: In [2]: def bar(): ...: return [] ...: In [3]: a=[] In [4]: a += foo() In [5]: a Out[5]: [1, 2, 3] In [6]: a += bar() In [7]: a Out[7]: [1, 2, 3] Christian -- https://mail.python.org/mailman/listinfo/python-list
Re: Is there a way to get the following result in Python?
Peter Otten 在 2021年6月15日 星期二下午2:48:07 [UTC+8] 的信中寫道: > On 12/06/2021 04:02, Jach Feng wrote: > > def foo(): > > ... # do something > > ... > a = [] > for i in range(3): > > ... a.append(foo()) > > ... > a > > [] > The most natural way to achieve something similar is to replace append() > with extend(): > > >>> def foo(): return () > >>> a = [] > >>> for i in range(3): > a.extend(foo()) > > > >>> a > [] Yes, return a list and using extend() to collect value is exactly what I need! Thank you, Christian and Peter. --Jach -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
Greg Ewing 在 2021年6月15日 星期二下午3:01:46 [UTC+8] 的信中寫道: > On 15/06/21 3:18 pm, Jach Feng wrote: > > From a user's point, I don't really care how Python creates thoseinstances, > > > either using an already exist one or create a new one, as > > long as each element (and its sub-element) are independent from each > > other so a modification of one will not influence the other. The real > > problem is there are different methods can be used to build it and some > > will fail in this purpose. The * operator is one of them, but anyone > > else? I really like to know:-) > This really has nothing to do with how the tuples are created. > It all depends on what you choose to put in them. > > When you use square brackets to build a list, you can be sure that > it will create a new list object each time. > > Also, if you create two tuples, by any means, containing distinct > elements, you can be sure that you will get two distinct tuple > objects. > > So, if you do this: > > a = [1, 2] > b = [1, 2] > c = [1, 2] > d = [1, 2] > > s = (a, b) > t = (c, d) > > then you are guaranteed to get four different list objects and > two diffferent tuple objects. > > Does that help to ease your fears? > > -- > Greg But usually the list creation is not in simple way:-) for example: >>> a = [1,2] >>> m = [a for i in range(3)] >>> m [[1, 2], [1, 2], [1, 2]] >>> id(m[0]) == id(m[1]) == id(m[2]) True --Jach -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of pop() for dictionaries
On 15/06/2021 00:11, dn wrote: On 15/06/2021 09.18, BlindAnagram wrote: On 14/06/2021 20:43, Chris Angelico wrote: On Tue, Jun 15, 2021 at 5:41 AM BlindAnagram ... No it isn't hard to use popitem() but it evidently proved hard for me to remember that it was there. If that's a problem, you're going to love using deques with their 'popping from the left' and 'popping from the right' concepts! I think the difference here is that I know I am going to have to look at the documentation for dequeue when I want to use it. For lists, sets and dictionaries, I don't expect to look at the documentation and pop() seemed a good bet for what I wanted to do. I don't know if you are ComSc student or not, but there isn't even consistency at the theoretical level. I first arrived at the concept of "queuing" and "dequeuing" (NB the latter is not the same as the Python Collections module "deque" library) whilst studying Queue Theory in Operations Research. At about the same time, my ComSc studies took me into "stacks". My student days are well over (about 60 years over). Queues are known as FIFO constructs - "first-in, first-out". Stacks are somewhat the opposite: LIFO - "last-in, first-out". The "pop" operation was defined as taking the "next" item from the queue or the "last" item from a stack (the opposite of "push"). However, between queue and stack, the term "next" refers to opposite ends of the (implementing in Python) list! In fact, coming from a Burroughs mainframe, which ran on "stack architecture" (cf IBM's multiplicity of "ALU registers"), it came as something of a surprise when programming languages started allowing me to "pop" elements that weren't at the LIFO-end of the 'list', eg list.pop( 3 ) where len( list ) > 4! Next consider how the terms "next" and "element" factor into the thinking. If we consider a (Python) list there is an implied sequence of elements based upon their relative position. Notice also that the basic implementation of list.pop() is LIFO! Whereas, the definition of a set involves no concept of sequence or order - only of membership (and that the elements are "hashable"). Accordingly, a pop() operation returns an "arbitrary value", cf 'next please'. Similarly, a dict's keys are referred-to as hashable, with the idea of "random access" to an element via its key (cf the "sequential access" of a list). Thus, we can ask to pop() a dict, but only if we provide a key - in which case, pop( key ) is the same as dict[ key ] except that the key-value pair is also removed from the dict! Recall though, it is possible to use list.pop() without any argument. So, consistency has been thrown-out-the-window there as well. Also, with LIFO in-mind, Python v3.7 brought a concept of 'sequence' (population order) to dicts, and thus we now have this "guarantee" in popitem() - and thus a memory-confusion for those of us who learned the original "arbitrary" definition - confusion both of dict behavior and of dict.popitem() specifically! Worse confusion awaits (and referring to a conversation 'here' last week) Python's pop() exhibits elements of both an "expression" and of a "statement", ie it not only returns a value, but it affects (?"side-effects") the underlying collection. Thus, no pop() for strings, tuples, etc, because they are immutable collections! The action of pop() is clearly inconsistent across types of collection. It's effect is data-structure dependent because the purposes of those structures are inherently different. "Consistency" would aid memory, but "polymorphism" can only deliver functionality according to the characteristics of the specific data-type! Yes, but we can still seek consistency where it is possible Having entered the queue-of-life a long time ago, and shuffling ever closer to 'the end of the line', this memory-challenged 'silver-surfer' prefers to reserve pop() for straightforward stacks and lists, which implies quite enough inconsistency, without trying to convolute my mind to pop()-ing dicts, sets (or 'worse'!). That said, whether I actually use dict.pop() or not, these 'features' which are consistent in name but not necessarily in arguments or effects, contribute to Python's great flexibility and power! Thank goodness for help() and the Python docs... I don't like 'pop's at all since it meant that a valve had exploded on the Ferranti Pegasus that was my first encounter with computers. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of pop() for dictionaries
On 15/06/2021 01:36, Terry Reedy wrote: On 6/14/2021 5:18 PM, BlindAnagram wrote: I believe that consistency in how methods common to different types work is useful since it adds to the coherence of the language as a whole and avoids the need to remember special cases. Each collection class *is* a special case, and pop has to be adjusted to each. However, you seem to have missed an essential commonality. Lists and dicts are both subscripted classes. So the basic API is col.pop(sub), which removes and returns the sub item, whereas col[sub] leaves and returns. Lists have a special index, -1, the most commonly used, so that is the default. In fact, when I proposed list.pop(), I only proposed that, as I wanted pop to be the inverse of append, so a list could be used as a stack. Bad list subscripts are an error (unless one is slicing), whereas where dicts allow a default (when subscripted with the get method). Hence the optional default only for dicts. At one time, dicts, like sets, were unordered collections (of functional item pairs). dict.pop(), with no arg, could have been used to return a random 2-ple, but Guido is generally against having return types depend on arguments. So a new popxxx name was added. Note that deques have a popleft in addition to pop (right). Thanks for the interesting history. Having found that dict.pop() caused an error, I did wonder whether it should have returned a (key, value) pair but quickly came to the conclusion that this would be awful because it would be inconsistent with the normal value returned by pop(x). Sadly this did not result in any recollection that there was a popitem() :-( Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: optimization of rule-based model on discrete variables
Il Tue, 15 Jun 2021 10:40:05 +1200, Greg Ewing ha scritto: > On 15/06/21 12:51 am, Elena wrote: > Hmmm, so the problem breaks down into two parts: > (1) find a vector Y that minimises g (2) find a set of rules that will > allow you to predict each component of Y from its corresponding X values > > Is that right? Correct, the split can be an interesting approach. > > I ztill don't really understand. What are you going to do with this > function f once you have it? > > I would have thought the idea was that if someone gives you a new > mixture X[n+1] you can use f to predict how well it will work. > But that will just give you a y[n+1], and it's not clear what to do with > that. Do you append it to Y and feed an n+1 component vector into g? > > I think I still need more information about the underlying problem > before I can help you much. After the optimization, I will use f just to predict new Xi. Thanks -- https://mail.python.org/mailman/listinfo/python-list
Re: Php vs Python gui (tkinter...) for small remote database app
Op 14-06-2021 om 21:17 schreef Pascal B via Python-list: Hi, I would like to know if for a small app for instance that requires a connection to a remote server database if php is more suitable than Python mainly regarding security. Php requires one port for http and one port for the connection to the database open. If using Python with a tkinter gui, I understand a small app can connect to a database so only one port to the database would need to be accessed/open listening to connection. So I would need to worry less about security if using Python over Php for something small, like a small python app that I give over to users. Am I missing something in this assertion? There is no difference regarding security concerns. In the case of a PHP (or any web app for that matter) you indeed have to worry about the security of the connection to the browser. But, e.g. the access to the database is only in one place, on the server. If you use a Tkinter application, each user will have the access to the database at his/her own machine, causing other worries than connection security. The attack vector may be different, but the worries are no less or more in one of the solutions. First investigate what you need to be afraid of/worried about, do not make a decision on a simple criterion like the number of connections. -- Met vriendelijke groet / Kind regards Menno Hölscher -- https://mail.python.org/mailman/listinfo/python-list
Re: optimization of rule-based model on discrete variables
Il Tue, 15 Jun 2021 01:53:09 +, Martin Di Paola ha scritto:
> From what I'm understanding it is an "optimization problem" like the
> ones that you find in "linear programming".
>
> But in your case the variables are not Real (they are Integers) and the
> function to minimize g() is not linear.
>
> You could try/explore CVXPY (https://www.cvxpy.org/) which it's a solver
> for different kinds of "convex programming". I don't have experience
> with it however.
>
> The other weapon in my arsenal would be Z3
> (https://theory.stanford.edu/~nikolaj/programmingz3.html) which it's a
> SMT/SAT solver with a built-in extension for optimization problems.
>
> I've more experience with this so here is a "draft" of what you may be
> looking for.
>
>
> from z3 import Integers, Optimize, And, If
>
> # create a Python array X with 3 Z3 Integer variables named x0, x1, x2 X
> = Integers('x0 x1 x2')
> Y = Integers('y0 y1')
>
> # create the solver solver = Optimize()
>
> # add some restrictions like lower and upper bounds for x in X:
>solver.add(And(0 <= x, x <= 2)) # each x is between 0 and 2
> for y in Y:
>solver.add(And(0 <= y, y <= 2))
>
> def f(X):
># Conditional expression can be modeled too with "If"
># These are *not* evaluated like a normal Python "if" but # modeled
>as a whole. It'll be the solver which will "run it"
>return If(
> And(x[0] == 0, x[1] == 0), # the condition Y[0] == 0, # Y[0] will
> *must* be 0 *if* the condition holds Y[0] == 2 # Y[0] will *must*
> be 2 *if* the condition doesn't hold )
>
> solver.add(f(X))
>
> # let's define the function to optimize g = Y[0]**2 solver.maximize(g)
>
> # check if we have a solution solver.check() # this should return 'sat'
>
> # get one of the many optimum solutions solver.model()
>
>
> I would recommend you to write a very tiny problem with 2 or 3 variables
> and a very simple f() and g() functions, make it work (manually and with
> Z3) and only then build a more complex program.
>
> You may find useful (or not) these two posts that I wrote a month ago
> about Z3. These are not tutorials, just personal experience with a
> concrete example.
>
> Combine Real, Integer and Bool variables:
> https://book-of-gehn.github.io/articles/2021/05/02/Planning-Space-
Missions.html
>
> Lookup Tables (this may be useful for programming a f() "variable"
> function where the code of f() (the decision tree) is set by Z3 and not
> by you such f() leads to the optimum of g())
> https://book-of-gehn.github.io/articles/2021/05/26/Casting-Broadcasting-
LUT-and-Bitwise-Ops.html
>
>
> Happy hacking.
> Martin.
>
>
Interesting, I completely didn't know about this Z3 tool, I'll try to go
into that.
Thank you for hint.
BTW the first two links I think are broken.
Ele
--
https://mail.python.org/mailman/listinfo/python-list
Re: Where did the message go?
On 14/06/2021 20:58, dn wrote:
On 15/06/2021 01.00, Grimble wrote:
I have two machines running Mageia 8 and Python 2.8.9, They use the same
Python script to maintain a list of changed packages from dnf update and
dnf install. In addition the script sends a short email message to my
main email address. The problem is: the message from machine B arrives,
the message from machine H does not.
The part of the script that sends the message is:
with open('email.txt') as fmail:
msg = EmailMessage()
msg.set_content(fmail.read())
msg['Subject'] = 'System update'
msg['From'] = sysname
msg['To'] = 'gra...@.' (details removed to protect the
innocent)
# Send the message via our own SMTP server.
s = smtplib.SMTP('localhost')
s.set_debuglevel(True)
s.send_message(msg)
s.quit()
The last lines of s.set_debuglevel are
reply: retcode (250); Msg: b'2.0.0 Ok: queued as B57B42C042F'
data: (250, b'2.0.0 Ok: queued as B57B42C042F')
send: 'quit\r\n'
reply: b'221 2.0.0 Bye\r\n'
reply: retcode (221); Msg: b'2.0.0 Bye'
The SMTP part of the system is working (hence this message).
The message from machine B correctly interprets "sysname" as
sysn...@sysname.. i.e a valid addr4ess.
Where do I look now, please?
That's machine B, but the issue is with machine H.
Have you compared the contents of the two machines' /var/log/maillog?
Thanks for reminding me of the log files. I've worked out that the
message on machine H (for haydn, which shows my preferred music genre)
was bouncing because haydn.. was not a registered subdomain with
my ISP, whereas bach.. was registered. Sorted now.
--
Grimble
Registered Linux User #450547
Machine 'Bach' running Plasma 5.20.4 on 5.10.43-desktop-1.mga8 kernel.
Mageia release 8 (Official) for x86_64
--
https://mail.python.org/mailman/listinfo/python-list
Help with Python circular error
Hi to everyone, I am having a problem with this error, I created a package and uploaded it to Test PyPi, but I can not get it to work, can someone help me please? https://test.pypi.org/manage/project/videotesting/releases/' The error: /home/user/anaconda3/envs/testing/bin/python /home/user/devel/python.assignments/topgis-viz/topgis-test.py Traceback (most recent call last): File "/home/user/devel/python.assignments/topgis-viz/topgis-test.py", line 10, in from videotesting import downsample_and_save_npz File "/home/user/anaconda3/envs/testing/lib/python3.8/site-packages/videotesting/__init__.py", line 7, in from videotesting import extract_video ImportError: cannot import name 'extract_video' from partially initialized module 'videotesting' (most likely due to a circular import) (/home/user/anaconda3/envs/testing/lib/python3.8/site-packages/videotesting/__init__.py) -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
On Wed, Jun 16, 2021 at 2:18 AM Dieter Maurer wrote: > > Chris Angelico wrote at 2021-6-15 19:08 +1000: > >On Tue, Jun 15, 2021 at 6:32 PM Dieter Maurer wrote: > >> > >> Chris Angelico wrote at 2021-6-15 05:35 +1000: > >> >On Tue, Jun 15, 2021 at 5:12 AM Jach Feng wrote: > >> >> > >> >> >>> n = [(1,2) for i in range(3)] > >> >> >>> n > >> >> [(1, 2), (1, 2), (1, 2)] > >> >> >>> id(n[0]) == id(n[1]) == id(n[2]) > >> >> True > >> > > >> >This is three tuples. Tuples are immutable and you get three > >> >references to the same thing. > >> > >> In addition: object identity (as revealed by `id(...)`) is > >> an implementation detail. Do not rely on it! > > > >Hmm, not always. In this case, object identity isn't guaranteed - > >every literal could give you a unique object - but in other cases, > >object identity is a language guarantee. For instance: > > As far as I know, there are no guarantees are the language level. > There are some (partially documented) implementation details > for CPython (which is just one possible implementation). Yes there are - plenty of them :) The example I gave is a language guarantee. Object identity is maintained in various places, and MUST be; in fact, I've heard tell that PyPy actually has to do some shenanigans to ensure that identities can be tracked across certain types of optimizations (where the object mightn't actually exist temporarily). ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Where did the message go?
On Wed, Jun 16, 2021 at 2:41 AM Grimble wrote: > Thanks for reminding me of the log files. I've worked out that the > message on machine H (for haydn, which shows my preferred music genre) > was bouncing because haydn.. was not a registered subdomain with > my ISP, whereas bach.. was registered. Sorted now. > I like your naming convention :) ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
On 2021-06-15 17:18, Dieter Maurer wrote: Chris Angelico wrote at 2021-6-15 19:08 +1000: On Tue, Jun 15, 2021 at 6:32 PM Dieter Maurer wrote: Chris Angelico wrote at 2021-6-15 05:35 +1000: >On Tue, Jun 15, 2021 at 5:12 AM Jach Feng wrote: >> >> >>> n = [(1,2) for i in range(3)] >> >>> n >> [(1, 2), (1, 2), (1, 2)] >> >>> id(n[0]) == id(n[1]) == id(n[2]) >> True > >This is three tuples. Tuples are immutable and you get three >references to the same thing. In addition: object identity (as revealed by `id(...)`) is an implementation detail. Do not rely on it! Hmm, not always. In this case, object identity isn't guaranteed - every literal could give you a unique object - but in other cases, object identity is a language guarantee. For instance: As far as I know, there are no guarantees are the language level. There are some (partially documented) implementation details for CPython (which is just one possible implementation). There is a language guarantee that every object has an identity that's given by 'id' and that 'x is y' is equivalent to 'id(x) == id(y)'. In CPython it happens to be the address of the object, but that's an implementation detail. -- https://mail.python.org/mailman/listinfo/python-list
Re: Help with Python circular error
On Wed, Jun 16, 2021 at 2:45 AM Arak Rachael wrote: > > Hi to everyone, > > I am having a problem with this error, I created a package and uploaded it to > Test PyPi, but I can not get it to work, can someone help me please? > > https://test.pypi.org/manage/project/videotesting/releases/' > > The error: > > /home/user/anaconda3/envs/testing/bin/python > /home/user/devel/python.assignments/topgis-viz/topgis-test.py > Traceback (most recent call last): > File "/home/user/devel/python.assignments/topgis-viz/topgis-test.py", line > 10, in > from videotesting import downsample_and_save_npz > File > "/home/user/anaconda3/envs/testing/lib/python3.8/site-packages/videotesting/__init__.py", > line 7, in > from videotesting import extract_video > ImportError: cannot import name 'extract_video' from partially initialized > module 'videotesting' (most likely due to a circular import) > (/home/user/anaconda3/envs/testing/lib/python3.8/site-packages/videotesting/__init__.py) > Hard to diagnose without the source code, but I'm thinking that your __init__.py is probably trying to import from elsewhere in the package? If so, try "from . import extract_video" instead. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Where did the message go?
On 16/06/2021 04.47, Chris Angelico wrote: > On Wed, Jun 16, 2021 at 2:41 AM Grimble wrote: >> Thanks for reminding me of the log files. I've worked out that the >> message on machine H (for haydn, which shows my preferred music genre) >> was bouncing because haydn.. was not a registered subdomain with >> my ISP, whereas bach.. was registered. Sorted now. >> > > I like your naming convention :) He's playing your tune! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Help with Python circular error
On 2021-06-15 17:49, Chris Angelico wrote: On Wed, Jun 16, 2021 at 2:45 AM Arak Rachael wrote: Hi to everyone, I am having a problem with this error, I created a package and uploaded it to Test PyPi, but I can not get it to work, can someone help me please? https://test.pypi.org/manage/project/videotesting/releases/' The error: /home/user/anaconda3/envs/testing/bin/python /home/user/devel/python.assignments/topgis-viz/topgis-test.py Traceback (most recent call last): File "/home/user/devel/python.assignments/topgis-viz/topgis-test.py", line 10, in from videotesting import downsample_and_save_npz File "/home/user/anaconda3/envs/testing/lib/python3.8/site-packages/videotesting/__init__.py", line 7, in from videotesting import extract_video ImportError: cannot import name 'extract_video' from partially initialized module 'videotesting' (most likely due to a circular import) (/home/user/anaconda3/envs/testing/lib/python3.8/site-packages/videotesting/__init__.py) Hard to diagnose without the source code, but I'm thinking that your __init__.py is probably trying to import from elsewhere in the package? If so, try "from . import extract_video" instead. Well, the traceback says that videotesting/__init__.py has: from videotesting import extract_video so it is trying to import from itself during initialisation. -- https://mail.python.org/mailman/listinfo/python-list
Re: Php vs Python gui (tkinter...) for small remote database app
On 2021-06-15, Menno Holscher wrote: > There is no difference regarding security concerns. I find that hard to believe given the long list of CVEs I've just had to sort through for even fairly recent versions of PHP. I just can't belive that Python has anywhere close to that many secruity issues. -- Grant Edwards grant.b.edwardsYow! I'd like some JUNK at FOOD ... and then I want to gmail.combe ALONE -- -- https://mail.python.org/mailman/listinfo/python-list
Re: Help with Python circular error
On Wed, Jun 16, 2021 at 3:17 AM MRAB wrote: > > On 2021-06-15 17:49, Chris Angelico wrote: > > On Wed, Jun 16, 2021 at 2:45 AM Arak Rachael > > wrote: > >> > >> Hi to everyone, > >> > >> I am having a problem with this error, I created a package and uploaded it > >> to Test PyPi, but I can not get it to work, can someone help me please? > >> > >> https://test.pypi.org/manage/project/videotesting/releases/' > >> > >> The error: > >> > >> /home/user/anaconda3/envs/testing/bin/python > >> /home/user/devel/python.assignments/topgis-viz/topgis-test.py > >> Traceback (most recent call last): > >> File "/home/user/devel/python.assignments/topgis-viz/topgis-test.py", > >> line 10, in > >> from videotesting import downsample_and_save_npz > >> File > >> "/home/user/anaconda3/envs/testing/lib/python3.8/site-packages/videotesting/__init__.py", > >> line 7, in > >> from videotesting import extract_video > >> ImportError: cannot import name 'extract_video' from partially initialized > >> module 'videotesting' (most likely due to a circular import) > >> (/home/user/anaconda3/envs/testing/lib/python3.8/site-packages/videotesting/__init__.py) > >> > > > > Hard to diagnose without the source code, but I'm thinking that your > > __init__.py is probably trying to import from elsewhere in the > > package? If so, try "from . import extract_video" instead. > > > Well, the traceback says that videotesting/__init__.py has: > from videotesting import extract_video > > so it is trying to import from itself during initialisation. Yes, but what we can't tell is what the intention is. It could be trying to import from its own package (in which case my suggestion would be correct), or it could be trying to import from something completely different (in which case the solution is to rename something to avoid the conflict). Or it could be something else entirely. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
On 15/06/21 7:32 pm, Jach Feng wrote: But usually the list creation is not in simple way:-) for example: a = [1,2] m = [a for i in range(3)] m [[1, 2], [1, 2], [1, 2]] id(m[0]) == id(m[1]) == id(m[2]) True The first line is only executed once, so you just get one list object [1, 2]. You then refer to that object three times when you build the outer list. To get three different [1, 2] lists you would need something like this: m = [[1,2] for i in range(3)] This executes the [1, 2] expression 3 times. Because lists are mutable, you can be sure that this will give you 3 distinct list objects. -- Greg -- https://mail.python.org/mailman/listinfo/python-list
Re: optimization of rule-based model on discrete variables
On 15/06/21 10:07 pm, Elena wrote: After the optimization, I will use f just to predict new Xi. So you're going to use f backwards? I don't see how that will work. Where are you going to find a new yi to feed into the inverse of f? I think I don't understand what role g plays in all of this. If the ultimate goal is to find a better mixture, you need some kind of figure of merit for an individual mixture. But you don't have that, you only have this thing g that somehow depends on all of your mixtures at once. I'm still not seeing the big picture. -- Greg -- https://mail.python.org/mailman/listinfo/python-list
Re: Php vs Python gui (tkinter...) for small remote database app
Op 15-06-2021 om 19:14 schreef Grant Edwards: On 2021-06-15, Menno Holscher wrote: There is no difference regarding security concerns. I find that hard to believe given the long list of CVEs I've just had to sort through for even fairly recent versions of PHP. I just can't belive that Python has anywhere close to that many secruity issues. An excellent example. The "concerns" here are "Is this platform safe?" and "Does the supplier/community react promptly to security problems?". In case of PHP indeed the safety of the platform is a worry, however, apparently if there is a problem, action is taken. How does the Tkinter/TCL/TK software or the PyQt/Qt do in that respect? Just looking at the number of CVEs, is that enough? What if one of these stacks has few, but long outstanding security problems? Would that be better or worse than the situation for PHP? As an aside, I do not know the amount of CVEs PHP nor Python is receiving. When I search the NIST CVE database for the word Python I get 43 hits for the last 3 months. None of those are against the language or the CPython interpreter and only 1 against a Standard Library package or module (urllib3). A lot of the others are for web frameworks and extensions for those, as well as Tensorflow. So as you argue, it seems Python does really well as a secure development platform. -- Met vriendelijke groet / Kind regards Menno Hölscher -- https://mail.python.org/mailman/listinfo/python-list
RE: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
May I ask if there are any PRACTICAL differences if multiple immutable tuples share the same address or not? I mean if I use a tuple in a set or as the key in a dictionary and a second one comes along, will it result in two entries one time and only one the other time? Some languages I use often have a lazy evaluation where things are not even copied when doing some things and only copied if absolutely needed as in when you make a change. So you can create say a data.frame then make another from it with some columns added and removed and the storage used does not change much, but add or remove one or two, and suddenly entire large amounts get copied. So by that argument, you could have the copies of the list also be the same at first and since they are mutable, they might diverge later or not but tuples would never change so why not share if the compiler or interpreter was set to use less space when possible. Now if you really still want true copies, what ways might fool a compiler? NoDup = [(5, 2), (6-1, 6/3), (12%7, 1/1 + 1/1)] -Original Message- From: Python-list On Behalf Of Greg Ewing Sent: Tuesday, June 15, 2021 7:11 PM To: [email protected] Subject: Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it? On 15/06/21 7:32 pm, Jach Feng wrote: > But usually the list creation is not in simple way:-) for example: a = [1,2] m = [a for i in range(3)] m > [[1, 2], [1, 2], [1, 2]] id(m[0]) == id(m[1]) == id(m[2]) > True The first line is only executed once, so you just get one list object [1, 2]. You then refer to that object three times when you build the outer list. To get three different [1, 2] lists you would need something like this: m = [[1,2] for i in range(3)] This executes the [1, 2] expression 3 times. Because lists are mutable, you can be sure that this will give you 3 distinct list objects. -- Greg -- https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
On Wed, Jun 16, 2021 at 10:17 AM Avi Gross via Python-list wrote: > > May I ask if there are any PRACTICAL differences if multiple immutable > tuples share the same address or not? No, there aren't. It's nothing more than an (optional) optimization. This is true of every immutable type, including strings (both text and byte), numbers (int, float, etc), and less obvious ones like code objects. (Though not function objects. They're mutable.) > I mean if I use a tuple in a set or as the key in a dictionary and a second > one comes along, will it result in two entries one time and only one the > other time? Nope; dictionaries use the *value*, so even if you have two distinct tuples with the same value, they will be considered equal. > Some languages I use often have a lazy evaluation where things are not even > copied when doing some things and only copied if absolutely needed as in > when you make a change. So you can create say a data.frame then make > another from it with some columns added and removed and the storage used > does not change much, but add or remove one or two, and suddenly entire > large amounts get copied. > > So by that argument, you could have the copies of the list also be the same > at first and since they are mutable, they might diverge later or not but > tuples would never change so why not share if the compiler or interpreter > was set to use less space when possible. Hmm. Copy-on-write is permissible but wouldn't be worthwhile in most cases. But I'm sure there are situations where it would be worth it. > Now if you really still want true copies, what ways might fool a compiler? > > NoDup = [(5, 2), (6-1, 6/3), (12%7, 1/1 + 1/1)] > Note that these would all compare equal, but they are NOT indistinguishable. The first one has a pair of integers, the other two have an int and a float. But with the two that *are* indistinguishable, CPython 3.10 folds them together and has two references to the same tuple. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
On 16/06/21 12:15 pm, Avi Gross wrote:
May I ask if there are any PRACTICAL differences if multiple immutable
tuples share the same address or not?
Only if some piece of code relies on the identity of tuples
by using 'is' or id() on them.
There's rarely any need to write code like that, though.
Normally you should compare tuples using '==', not 'is'.
Exceptions to this usually involve something like cacheing
where identity is only used for optimisation purposes,
and the end result doesn't depend in it.
I mean if I use a tuple in a set or as the key in a dictionary and a second
one comes along, will it result in two entries one time and only one the
other time?
Dicts and sets compare keys by equality, not identity, so
there is no problem here.
>>> a = 1
>>> b = 2
>>> t1 = (a, b)
>>> t2 = (a, b)
>>> t1 is t2
False
>>> d = {}
>>> d[t1] = 'spam'
>>> t2 in d
True
>>> s = set()
>>> s.add(t1)
>>> t2 in s
True
Some languages I use often have a lazy evaluation where things are not even
copied when doing some things and only copied if absolutely needed
> So by that argument, you could have the copies of the list also be the
> same at first and since they are mutable, they might diverge later
Python is not one of those languages, though, and it won't do things
like that. (At least not on its own -- you can certainly implement
such a lazily-copied data structure if you want.)
Now if you really still want true copies, what ways might fool a compiler?
I've shown one way above that works in CPython, but a smarter
implementation might notice that t1 and t2 will always be equal
and merge them.
NoDup = [(5, 2), (6-1, 6/3), (12%7, 1/1 + 1/1)]
CPython merges the last two of these, but not the first:
>>> NoDup = [(5, 2), (6-1, 6/3), (12%7, 1/1 + 1/1)]
>>> [id(x) for x in NoDup]
[4387029696, 4386827968, 4386827968]
The reason is that '/' does float division in Python 3. If you
use int division instead, they all get merged:
>>> NoDup = [(5, 2), (6-1, 6//3), (12%7, 1//1 + 1//1)]
>>> [id(x) for x in NoDup]
[4387030272, 4387030272, 4387030272]
So you need to be tricker than that to fool it!
The bottom line is, don't write code that depends on the identities
of immutable objects.
--
Greg
--
https://mail.python.org/mailman/listinfo/python-list
RE: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
Greg, My point was not to ASK what python does as much as to ask why it matters to anyone which way it does it. Using less space at absolutely no real expense is generally a plus. Having a compiler work too hard, or even ask the code to work too hard, is often a minus. If I initialized the tuples by calling f(5) and g(5) and so on, the compiler might not even be easily able to figure out that they all return the same thing. So should it make a run-time addition to the code so that after calculating the second, it should look around and if it matches the first, combine them? Again, I have seen languages where the implementation is to have exactly one copy of each unique string of characters. That can be useful but if it is done by creating some data structure and searching through it even when we have millions of unique strings, ... Heck, one excellent reason to use "constants" in your code (i.e. something immutable) is to allow such optimizations. In some programs, garbage collection is very active as things get copied and modified and parts released. So it can be worth some effort to mark some items as copy-on-change as they are often abandoned without changes. The common paradigm I often see is you bring in a structure like a data.frame with dozens of columns and then make a new variable containing a subset, perhaps in a different order and perhaps then then add another column made by some calculation like it being equal to the items in the column called "distance" divided by the column entries called "time" to make a speed column. You might graph the result and then make other such structures and graphs all without doing anything but reading some columns. If you then decided to just take a subset of the rows, or update even a single item in one column, sure, you then take a copy but only of the vectors that changed. Does python need something like this. I doubt it. Languages with such lazy features can do very powerful things but then need even more operators to force certain evaluations to be done in certain ways that leave other parts unevaluated. R, for amusement, has an operator called !! (named bang bang) for some such purposes and another operator !!! (obviously called The Big Bang) for others. But it has radical differences in philosophy as compared to something like python and each has a role and places it is easier to write some kinds of programs than others. The original question here was why there are different results. I think the answer to my question is that it does not matter for most purposes. I can think of one that MAYBE does. If an application has some kind of ceiling, such as calculating how much memory is left before deciding if a mail message is too big to send, and it sometimes runs on machines with different amounts of such resources, you can end up with a message being shunted along the way towards the destination (we are talking ages ago) and suddenly hitting a machine where it is tossed into junkmail as too big. So if your compiler/interpreter is one that allows you to use less memory in circumstances like we are discussing, you may not get what you think. Imagine a program that every time it creates a data structure, adds some measure like sizeof() the new item and halts if the size reached a gigabyte or perhaps charges extra because you used more of a resource. The programmer choosing the list versus tuple alternative, would get different behavior in such a hypothetical scenario. -Original Message- From: Python-list On Behalf Of Greg Ewing Sent: Tuesday, June 15, 2021 9:00 PM To: [email protected] Subject: Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it? On 16/06/21 12:15 pm, Avi Gross wrote: > May I ask if there are any PRACTICAL differences if multiple immutable > tuples share the same address or not? Only if some piece of code relies on the identity of tuples by using 'is' or id() on them. There's rarely any need to write code like that, though. Normally you should compare tuples using '==', not 'is'. Exceptions to this usually involve something like cacheing where identity is only used for optimisation purposes, and the end result doesn't depend in it. > I mean if I use a tuple in a set or as the key in a dictionary and a > second one comes along, will it result in two entries one time and > only one the other time? Dicts and sets compare keys by equality, not identity, so there is no problem here. >>> a = 1 >>> b = 2 >>> t1 = (a, b) >>> t2 = (a, b) >>> t1 is t2 False >>> d = {} >>> d[t1] = 'spam' >>> t2 in d True >>> s = set() >>> s.add(t1) >>> t2 in s True > Some languages I use often have a lazy evaluation where things are not > even copied when doing some things and only copied if absolutely > needed > So by that argument, you could have the copies of the list also be the > same at first and since they are mutable, they might div
Re: Behaviour of pop() for dictionaries
On 15/06/2021 21.37, BlindAnagram wrote: > On 15/06/2021 00:11, dn wrote: >> On 15/06/2021 09.18, BlindAnagram wrote: >>> On 14/06/2021 20:43, Chris Angelico wrote: On Tue, Jun 15, 2021 at 5:41 AM BlindAnagram >> ... > I think the difference here is that I know I am going to have to look at > the documentation for dequeue when I want to use it. For lists, sets and > dictionaries, I don't expect to look at the documentation and pop() > seemed a good bet for what I wanted to do. "What I expect" (aka 'dim/dusty recollection' or 'gut feel') is a good way to learn - match it with the Python REPL and a couple of experiments to 'prove' your expectation/recollection. Thereafter there is a far greater likelihood of "learning" - and remembering-correctly 'next time'... The other worthy technique in this field is "deliberate learning". Thus, spending some time studying the docs for the built-ins' functionality (and experimentation) to obviate the need to look-up that level of documentation. Contrary to the learning-practices of 'our day', these days there is a far lower reliance on memory, in favor of rapid-access to reference data, eg the Python docs and REPL's help(), etc. Accordingly, the 'bits' that we might think of as 'minimum knowledge' may be seen as somewhat "arbitrary". (actually it is called Curriculum Design, but given that there is no single application-area for Python there is no single curriculum either) No matter: we are completely correct, no question - and what would 'they' know anyway? PS we were also subject to the idea that intelligence/ability was largely genetic and thus only available in a fixed quantity - either one is 'good' at something, or not (full stop). These days we know ourselves (brains) to be more "plastic", and that with sufficient motivation and effort we can learn 'new stuff', regardless of whether we were 'good at it' yesterday! >> I don't know if you are ComSc student or not, but there isn't even >> consistency at the theoretical level. I first arrived at the concept of >> "queuing" and "dequeuing" (NB the latter is not the same as the Python >> Collections module "deque" library) whilst studying Queue Theory in >> Operations Research. At about the same time, my ComSc studies took me >> into "stacks". > > My student days are well over (about 60 years over). Someone with an even longer beard than mine! We could compare walking sticks... Oh wait, aren't we talking about Python. I'm amazed at how stuff from 'history' is recyclable and becomes applicable to whichever is described as 'today'. Even 'new' things in computing! There's always something new to adapt, if not learn... ... > Yes, but we can still seek consistency where it is possible Trouble is, there are different ways of looking at 'stuff', and thus different dimensions of "consistent". Thus, dict methods try to be consistent to the way a dict behaves. Whereas being 'consistent' with other collections: sets, lists, strings, etc; comes second. Oops if not OOPs! >> Having entered the queue-of-life a long time ago, and shuffling ever >> closer to 'the end of the line', this memory-challenged 'silver-surfer' >> prefers to reserve pop() for straightforward stacks and lists, which >> implies quite enough inconsistency, without trying to convolute my mind >> to pop()-ing dicts, sets (or 'worse'!). I still haven't recalled a single occasion when I've used set.pop() or dict.pop(). Was that because I didn't recall their availability at the right time, or does my mind simply not see that 'consistency' yours recognises? (not that it matters particularly) >> That said, whether I actually use dict.pop() or not, these 'features' >> which are consistent in name but not necessarily in arguments or >> effects, contribute to Python's great flexibility and power! Thank >> goodness for help() and the Python docs... > > I don't like 'pop's at all since it meant that a valve had exploded on > the Ferranti Pegasus that was my first encounter with computers. That does pre-date the prehistoric computers I managed to play-with! There's apparently one in LON's Science Museum. Don't know if it was there when I last visited (c.15 years ago) - I do recall their Babbage implementations and an analog computer (looked like some torture rack) similar to one that my father used way, way, way-back. Similarly, considering it/another similar exhibit and talking with our friends about the 'joys' of using paper tape (and its talent for wrapping itself around anything and everything, except where you wanted it) and those of (assembler) programming delays in order to store data on rotating mag-drums. Those were the days! (or maybe not) -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Why the list creates in two different ways? Does it cause by the mutability of its elements? Where the Python document explains it?
On Wed, Jun 16, 2021 at 12:44 PM Avi Gross via Python-list wrote: > > Greg, > > My point was not to ASK what python does as much as to ask why it matters to > anyone which way it does it. Using less space at absolutely no real expense > is generally a plus. Having a compiler work too hard, or even ask the code > to work too hard, is often a minus. > > If I initialized the tuples by calling f(5) and g(5) and so on, the compiler > might not even be easily able to figure out that they all return the same > thing. So should it make a run-time addition to the code so that after > calculating the second, it should look around and if it matches the first, > combine them? Again, I have seen languages where the implementation is to > have exactly one copy of each unique string of characters. That can be > useful but if it is done by creating some data structure and searching > through it even when we have millions of unique strings, ... "some data structure" being, in all probability, a hashtable, so that searching through it is fast :) Python lets you do this via sys.intern(), and CPython automatically does it for any strings that look like identifiers. Your analyses are both correct; but the compiler is generally allowed to work hard, because its work can be dumped out into a file for next time. Consider this code: def make_adder(n): def adder(values): return [v + n for v in values] return adder This has four distinct code blocks (module, make_adder, adder, and the list comp), all of which are represented as immutable code objects, and can be saved into the .pyc file. If the compiler has to do extra work, that's fine! And in fact, it does a LOT of constant folding and other optimizations, based on what it can know about immediately. Everything else (constructing function objects, constructing lists, etc) is done at run time, although sometimes it's worth considering "function definition time" as a separate phase of execution (since, in many Python modules, that all happens at the very start of execution). Optimizations done at that point are potentially more expensive, since they might be done multiple times - imagine calling make_adder in a loop. But since the code object can be used as-is, it's no trouble to keep all the optimizations :) ChrisA -- https://mail.python.org/mailman/listinfo/python-list
