Re: Optional arguments in a class behave like class attributes.

2022-10-17 Thread Antoon Pardon

You can use the following decorator for what you probably want.

def copy_defaults(func):
"""
This decorator makes that defaults values are copied on a call.
"""

signature = inspect.signature(func)
parameter_items = list(signature.parameters.items())

@wraps(func)
def wrapper(*args, **kwds):
newargs = list(args)
tail_parameters = parameter_items[len(args):]
for name, parameter in tail_parameters:
try:
newargs.append(kwds[name])
del kwds[name]
except KeyError:
if parameter.default is not Parameter.empty:
newargs.append(copy.deepcopy(parameter.default))
else:
break
return func(*newargs, **kwds)

return wrapper

class GameOne:
  @copy_defaults
  def __init__(self, games = []) -> None:
self.games = games

# Results I got after using this decorator in your code

Using a list []
Using a dictionary {}
Using an object []

Op 16/10/2022 om 12:48 schreef Abderrahim Adrabi:

Hi all,

I tried to create a class with some optional arguments as always, but this
time I used the default values to be lists, dictionaries, and object
references.

So, these default values behave like class attributes, here is a demo:

# Using a list -
class GameOne:
   def __init__(self, games = []) -> None:
 self.games = games

h = GameOne()
h.games.append("List, the first round")

g = GameOne()
g.games.append("List, the second round")

k = GameOne()
print('Using a list', k.games)

# Using a dictionary --
class GameTwo:
   def __init__(self, games = {}) -> None:
 self.games = games

h = GameTwo()
h.games['1er'] = "Dictionary, the first round"

g = GameTwo()
g.games['2ed'] = "Dictionary, the second round"

k = GameTwo()
print('Using a dictionary', k.games)

# Using an object --
class Bonus:
   def __init__(self) -> None:
 self.stages = []

class GameThree:
   def __init__(self, bonus = Bonus()) -> None:
 self.bonus = bonus

h = GameThree()
h.bonus.stages.append('Object, the first round')

g = GameThree()
g.bonus.stages.append('Object, the second round')

k = GameThree()
print('Using an object', k.bonus.stages)

# Results 

Using a list ['List, the first round', 'List, the second round']
Using a dictionary {'1er': 'Dictionary, the first round', '2ed':
'Dictionary, the second round'}
Using an object ['Object, the first round', 'Object, the second round']

# Used Python versions ---

3.5.1 (default, Dec  9 2015, 14:41:32)
[GCC 5.2.0]

3.7.14 (default, Sep  8 2022, 00:06:44)
[GCC 7.5.0]

3.8.6 (default, Jan 29 2021, 17:38:16)
[GCC 8.4.1 20200928 (Red Hat 8.4.1-1)]

3.9.9 (main, Nov 20 2021, 21:30:06)
[GCC 11.1.0]

My question: Is this normal behavior?

Thanks.

--
https://mail.python.org/mailman/listinfo/python-list


Re: Quick question about CPython interpreter

2022-10-17 Thread Chris Angelico
On Tue, 18 Oct 2022 at 03:51, Stefan Ram  wrote:
>
> MRAB  writes:
> >It can't optimise that because, say, 'print' could've been bound to a
> >function that rebinds 'str'.
>
>   It would be possible to find out whether a call of a function
>   named "print" is to the standard function, but the overhead
>   to do this in the end might slow down the execution.
>
>   In general, it can be possible that there could be optimizer
>   stages after compilation. So, one might write a small micro-
>   benchmark to be sure.
>

You'd also have to ensure that the stringification of the ID doesn't
change (which it can it it isn't a core data type), and the easiest
way to do THAT is to call str() on the ID every time and see if it's
the same...

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Find the path of a shell command

2022-10-17 Thread Grant Edwards
On 2022-10-15, Andreas Eder  wrote:
> On Mi 12 Okt 2022 at 05:00, Paulo da Silva 
>  wrote:
>
>> The simple question: How do I find the full path of a shell command
>> (linux), i.e. how do I obtain the corresponding of, for example,
>> "type rm" in command line?
>>
>> The reason:
>> I have python program that launches a detached rm. It works pretty
>> well until it is invoked by cron! I suspect that for cron we need
>> to specify the full path.

> Why not just use os.unlink ?

Because he's using 'rm' to recursively remove a large directory tree
many levels deep.

One might think that could be done by 

   os.removedirs(name)
   Remove directories recursively. [...]

But it doesn't appear so from the description:

Works like rmdir() except that, if the leaf directory is
successfully removed, removedirs() tries to successively remove
every parent directory mentioned in path until an error is raised
(which is ignored, because it generally means that a parent
directory is not empty). For example, os.removedirs('foo/bar/baz')
will first remove the directory 'foo/bar/baz', and then remove
'foo/bar' and 'foo' if they are empty. Raises OSError if the leaf
directory could not be successfully removed.


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Quick question about CPython interpreter

2022-10-17 Thread MRAB

On 2022-10-17 16:43, David Lowry-Duda wrote:

One can use the `dis` module and investigate the generated python
bytecode. For me, I get

# file "dis1.py"
thing = 123
for i in range(10):
  if "hi" == str(thing):
  print("found")
  break

The bytecode is then

1   0 LOAD_CONST   0 (123)
2 STORE_NAME   0 (thing)

2   4 LOAD_NAME1 (range)
6 LOAD_CONST   1 (10)
8 CALL_FUNCTION1
   10 GET_ITER
  >>   12 FOR_ITER28 (to 42)
   14 STORE_NAME   2 (i)

3  16 LOAD_CONST   2 ('hi')
   18 LOAD_NAME3 (str)
   20 LOAD_NAME0 (thing)
   22 CALL_FUNCTION1
   24 COMPARE_OP   2 (==)
   26 POP_JUMP_IF_FALSE   12

4  28 LOAD_NAME4 (print)
   30 LOAD_CONST   3 ('found')
   32 CALL_FUNCTION1
   34 POP_TOP

5  36 POP_TOP
   38 JUMP_ABSOLUTE   42
   40 JUMP_ABSOLUTE   12
  >>   42 LOAD_CONST   4 (None)
   44 RETURN_VALUE

I note that line 22 calls the function str repeatedly, and no
optimization is done here.

# file "dis2.py"
thing = 123
strthing = str(thing)
for i in range(10):
  if "hi" == strthing:
  print("found")
  break

This generates bytecode

1   0 LOAD_CONST   0 (123)
2 STORE_NAME   0 (thing)

2   4 LOAD_NAME1 (str)
6 LOAD_NAME0 (thing)
8 CALL_FUNCTION1
   10 STORE_NAME   2 (strthing)

3  12 LOAD_NAME3 (range)
   14 LOAD_CONST   1 (10)
   16 CALL_FUNCTION1
   18 GET_ITER
  >>   20 FOR_ITER24 (to 46)
   22 STORE_NAME   4 (i)

4  24 LOAD_CONST   2 ('hi')
   26 LOAD_NAME2 (strthing)
   28 COMPARE_OP   2 (==)
   30 POP_JUMP_IF_FALSE   20

5  32 LOAD_NAME5 (print)
   34 LOAD_CONST   3 ('found')
   36 CALL_FUNCTION1
   38 POP_TOP

6  40 POP_TOP
   42 JUMP_ABSOLUTE   46
   44 JUMP_ABSOLUTE   20
  >>   46 LOAD_CONST   4 (None)
   48 RETURN_VALUE

In short, it seems the cpython interpreter doesn't (currently) perform
this sort of optimization.

It can't optimise that because, say, 'print' could've been bound to a 
function that rebinds 'str'.

--
https://mail.python.org/mailman/listinfo/python-list


Re: Quick question about CPython interpreter

2022-10-17 Thread David Lowry-Duda
One can use the `dis` module and investigate the generated python 
bytecode. For me, I get


# file "dis1.py"
thing = 123
for i in range(10):
if "hi" == str(thing):
print("found")
break

The bytecode is then

  1   0 LOAD_CONST   0 (123)
  2 STORE_NAME   0 (thing)

  2   4 LOAD_NAME1 (range)
  6 LOAD_CONST   1 (10)
  8 CALL_FUNCTION1
 10 GET_ITER
>>   12 FOR_ITER28 (to 42)
 14 STORE_NAME   2 (i)

  3  16 LOAD_CONST   2 ('hi')
 18 LOAD_NAME3 (str)
 20 LOAD_NAME0 (thing)
 22 CALL_FUNCTION1
 24 COMPARE_OP   2 (==)
 26 POP_JUMP_IF_FALSE   12

  4  28 LOAD_NAME4 (print)
 30 LOAD_CONST   3 ('found')
 32 CALL_FUNCTION1
 34 POP_TOP

  5  36 POP_TOP
 38 JUMP_ABSOLUTE   42
 40 JUMP_ABSOLUTE   12
>>   42 LOAD_CONST   4 (None)
 44 RETURN_VALUE

I note that line 22 calls the function str repeatedly, and no 
optimization is done here.


# file "dis2.py"
thing = 123
strthing = str(thing)
for i in range(10):
if "hi" == strthing:
print("found")
break

This generates bytecode

  1   0 LOAD_CONST   0 (123)
  2 STORE_NAME   0 (thing)

  2   4 LOAD_NAME1 (str)
  6 LOAD_NAME0 (thing)
  8 CALL_FUNCTION1
 10 STORE_NAME   2 (strthing)

  3  12 LOAD_NAME3 (range)
 14 LOAD_CONST   1 (10)
 16 CALL_FUNCTION1
 18 GET_ITER
>>   20 FOR_ITER24 (to 46)
 22 STORE_NAME   4 (i)

  4  24 LOAD_CONST   2 ('hi')
 26 LOAD_NAME2 (strthing)
 28 COMPARE_OP   2 (==)
 30 POP_JUMP_IF_FALSE   20

  5  32 LOAD_NAME5 (print)
 34 LOAD_CONST   3 ('found')
 36 CALL_FUNCTION1
 38 POP_TOP

  6  40 POP_TOP
 42 JUMP_ABSOLUTE   46
 44 JUMP_ABSOLUTE   20
>>   46 LOAD_CONST   4 (None)
 48 RETURN_VALUE

In short, it seems the cpython interpreter doesn't (currently) perform 
this sort of optimization.


- DLD
--
https://mail.python.org/mailman/listinfo/python-list


Re: Quick question about CPython interpreter

2022-10-17 Thread Michael Torrie
On 10/14/22 16:25, DFS wrote:
> -
> this does a str() conversion in the loop
> -
> for i in range(cells.count()):
>if text == str(ID):
>  break
> 
> 
> -
> this does one str() conversion before the loop
> -
> strID = str(ID)
> for i in range(cells.count()):
>if text == strID:
>  break
> 
> 
> But does CPython interpret the str() conversion away and essentially do 
> it for me in the first example?

No.

You can use the dis module to show you what CPython is doing under the hood.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Optional arguments in a class behave like class attributes.

2022-10-17 Thread Chris Angelico
On Tue, 18 Oct 2022 at 01:39, Abderrahim Adrabi
 wrote:
> So, these default values behave like class attributes, here is a demo:
>
> # Using a list -
> class GameOne:
>   def __init__(self, games = []) -> None:
> self.games = games
>

This makes the default be a single list, the same list for all of
them. If you want the default to be "construct a new list", you'll
need something else:

def __init__(self, games=None):
if games is None: games = []

There is an open proposal to allow this syntax, which would do what you want:

def __init__(self, games=>[]):

However, this is not part of any current version of Python.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: for -- else: what was the motivation?

2022-10-17 Thread Robert Latest via Python-list
 wrote:
> I had another crazy thought that I AM NOT ASKING anyone to do. OK?
>
> I was wondering about a sort of catch method you could use that generates a
> pseudo-signal only when the enclosed preceding  loop exits normally as a
> sort of way to handle the ELSE need without the use of a keyword known by
> the language. All you would need is an object of the right kind that is
> thrown and optionally caught.


(untested)

try:
while condition:
if not do_something():
raise RuntimeError
except RuntimeError:
pass
else:
print('Loop exited normally')

Ironically, this again relies on the much-used "else" and adds the overhead of
exception handling. Also from a natural language perspective I find the "try
...  except ... else" clause just as questionable as "while ... else." Since
we're discussing weird keywords: Maybe we can find another use for "finally."
In fact, one could argue that "while ... finally" could make just as much sense
as "while ... else" (but I won't).

> Of course, even if I fleshed this out and even if anyone thought it made
> sense, there is no such need now as Python has made a choice that meets the
> need even if few may dare use it or even know about it! LOL!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Find the path of a shell command

2022-10-17 Thread Andreas Eder
On Mi 12 Okt 2022 at 05:00, Paulo da Silva 
 wrote:

> The simple question: How do I find the full path of a shell command
> (linux), i.e. how do I obtain the corresponding of, for example,
> "type rm" in command line?
>
> The reason:
> I have python program that launches a detached rm. It works pretty well
> until it is invoked by cron! I suspect that for cron we need to specify
> the full path.
> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin?
> What about other commands?

Why not just use os.unlink ?

'Andreas
-- 
https://mail.python.org/mailman/listinfo/python-list


Using Paramiko to submit job on SGE

2022-10-17 Thread Arshi Syed
Hi All,

I am trying to run a script-1 on a Linux server using a Paramiko ssh connection 
and this script-1 calls script-2 which ultimately submits a job using a qsub 
command, job starts on SGE and I can see it through qstat but everything stops 
as soon as the script-1 stops. It seems the SSH session is getting closed after 
script-1 execution.

Could any one of you help me in resolving this issue?

Thanks,

SAUZ
-- 
https://mail.python.org/mailman/listinfo/python-list


Quick question about CPython interpreter

2022-10-17 Thread DFS

-
this does a str() conversion in the loop
-
for i in range(cells.count()):
  if text == str(ID):
break


-
this does one str() conversion before the loop
-
strID = str(ID)
for i in range(cells.count()):
  if text == strID:
break


But does CPython interpret the str() conversion away and essentially do 
it for me in the first example?



--
https://mail.python.org/mailman/listinfo/python-list


Re: for -- else: what was the motivation?

2022-10-17 Thread Dennis Lee Bieber
On Wed, 12 Oct 2022 23:19:39 +0100, Rob Cliffe 
declaimed the following:

>I too have occasionally used for ... else.  It does have its uses. But 
>oh, how I wish it had been called something else more meaningful, 
>whether 'nobreak' or whatever.  It used to really confuse me.  Now I've 

"expired"?


-- 
Wulfraed Dennis Lee Bieber AF6VN
wlfr...@ix.netcom.comhttp://wlfraed.microdiversity.freeddns.org/
-- 
https://mail.python.org/mailman/listinfo/python-list


Optional arguments in a class behave like class attributes.

2022-10-17 Thread Abderrahim Adrabi
Hi all,

I tried to create a class with some optional arguments as always, but this
time I used the default values to be lists, dictionaries, and object
references.

So, these default values behave like class attributes, here is a demo:

# Using a list -
class GameOne:
  def __init__(self, games = []) -> None:
self.games = games

h = GameOne()
h.games.append("List, the first round")

g = GameOne()
g.games.append("List, the second round")

k = GameOne()
print('Using a list', k.games)

# Using a dictionary --
class GameTwo:
  def __init__(self, games = {}) -> None:
self.games = games

h = GameTwo()
h.games['1er'] = "Dictionary, the first round"

g = GameTwo()
g.games['2ed'] = "Dictionary, the second round"

k = GameTwo()
print('Using a dictionary', k.games)

# Using an object --
class Bonus:
  def __init__(self) -> None:
self.stages = []

class GameThree:
  def __init__(self, bonus = Bonus()) -> None:
self.bonus = bonus

h = GameThree()
h.bonus.stages.append('Object, the first round')

g = GameThree()
g.bonus.stages.append('Object, the second round')

k = GameThree()
print('Using an object', k.bonus.stages)

# Results 

Using a list ['List, the first round', 'List, the second round']
Using a dictionary {'1er': 'Dictionary, the first round', '2ed':
'Dictionary, the second round'}
Using an object ['Object, the first round', 'Object, the second round']

# Used Python versions ---

3.5.1 (default, Dec  9 2015, 14:41:32)
[GCC 5.2.0]

3.7.14 (default, Sep  8 2022, 00:06:44)
[GCC 7.5.0]

3.8.6 (default, Jan 29 2021, 17:38:16)
[GCC 8.4.1 20200928 (Red Hat 8.4.1-1)]

3.9.9 (main, Nov 20 2021, 21:30:06)
[GCC 11.1.0]

My question: Is this normal behavior?

Thanks.
-- 
https://mail.python.org/mailman/listinfo/python-list


Aw: Re: for -- else: what was the motivation?

2022-10-17 Thread Karsten Hilbert
> which had special combinations for all the BASIC keywords). And if you
> go this way, why not go a step further and dissociate the program from
> its linear text representation? Add footnotes, different views,
> hyperlinks, format mathematical expressions like formulas, etc.

http://literateprogramming.com/

Karsten
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: for -- else: what was the motivation?

2022-10-17 Thread Chris Angelico
On Mon, 17 Oct 2022 at 16:36, Antoon Pardon  wrote:
>
>
>
> Op 17/10/2022 om 04:01 schreef Chris Angelico:
> > On Mon, 17 Oct 2022 at 10:46,  wrote:
> >> My point Chris was that you can have a conversation where you are exploring
> >> and not proposing. Brainstorming, perhaps.
> > And my point is that either a proposal is a serious one that can
> > expect serious discussion, or it isn't. Yes, I'm aware that it wasn't
> > you who backpedalled as soon as any criticism was posted, but your
> > caveat comes to the same thing - if you're trying to avoid serious
> > criticism, you have to not post an idea.
>
> Your reaction was not serious criticisme but a belligerent reaction.
> You made it clear you wanted a fight. I choose not to enter that
> fight.
>

Well, if reacting strongly to a proposal to break LITERALLY EVERY
PYTHON PROGRAM EVER counts as not a serious criticism but a
belligerent reaction, then there's not really a lot of point
discussing further.

Bye.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list