Question regarding objects in __call__() methods

2018-03-25 Thread Arshpreet Singh
I am debugging a set of code which is something like this:
 
http://dpaste.com/1JXTCF0

I am not able to understand that what role internet object is playing and how I 
can  use/call it. 

As debugging the code I got at line 10. I am sending a request to particular 
API and returning a request_object . further deep down it generates the 
"response_object" as from my requirements that should be JSON object but I am 
only getting Python-Object in hexa form, is there any way I can get to know how 
to use internet_object so I can get to know how to use that internet_object 
with response.

I am also able to call __call__ method something like this:

def hierarchy_attach(env, parent):
svc = IMS(env)
svc(parent)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Accessing parent objects

2018-03-25 Thread Jugurtha Hadjar

On 03/24/2018 07:14 PM, D'Arcy Cain wrote:

class C1(dict):
   class C2(object):
 def f(self):
   return X['field']

O1 = C1()
O1['field'] = 1
O2 = O1.C2()
print(O2.f())


I prefer to *feed* the child to the parent or vice versa. Simplifies 
things like testing.


Something like this:

<-->

class C1(object):
    def __init__(self):
    self.child = None

    def foo(self):
    print("I am {self.__class__.__name__} foo".format(self=self))

    def adopt(self, child=None):
    self.child = child
    s = ("I am {self.__class__.__name__} and I adopted "
"{self.child.__class__.__name__}".format(self=self))
    print(s)


class C2(object):
    def __init__(self, parent=None):
    self.parent = parent
    def foo(self):
    print("I am {self.__class__.__name__} foo".format(self=self))
    self.parent.foo()

    def adoptme(self, parent=None):
    parent = parent or self.parent
    if parent is None:
    print("No parent yet")
    else:
    self.parent = parent
    parent.adopt(self)

c2 = C2()
c2.adoptme()    # No parent yet

c1 = C1()
c2.adoptme(c1)  # I am C1 and I adopted C2
c2.foo()    # I am C2 foo
    # I am C1 foo

c1.adopt(c2)    # I am C1 and I adopted C2

<>



--
~ Jugurtha Hadjar,

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


Re: Accessing parent objects

2018-03-25 Thread Jugurtha Hadjar

There was a typo in my original reply:

<>

class C1(object):
    def __init__(self):
    self.child = None

    def foo(self):
    print("I am {self.__class__.__name__} foo".format(self=self))

    def adopt(self, child=None):
    self.child = child
    s = ("I am {self.__class__.__name__} and I adopted "
"{self.child.__class__.__name__}".format(self=self))
    print(s)


class C2(object):
    def __init__(self, parent=None):
    self.parent = parent
    def foo(self):
    print("I am {self.__class__.__name__} foo".format(self=self))
    self.parent.foo()

    def adoptme(self, parent=None):
    s = "I am {self.__class__.__name__} looking for adoption"
    print(s.format(self=self))
    parent = parent or self.parent
    if parent is None:
    print("No parent yet")
    else:
    self.parent = parent
    parent.adopt(self)


c2 = C2()
c2.adoptme()    # No parent yet

c1 = C1()
c2.adoptme(c1)  # I am C2 looking for adoption
    # I am C1 and I adopted C2

c2.foo()    # I am C2 foo
    # I am C1 foo

c1.adopt(c2)    # I am C1 and I adopted C2

<>



--
~ Jugurtha Hadjar,

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


Re: Accessing parent objects

2018-03-25 Thread Chris Angelico
On Sun, Mar 25, 2018 at 8:37 PM, Jugurtha Hadjar
 wrote:
> On 03/24/2018 07:14 PM, D'Arcy Cain wrote:
>>
>> class C1(dict):
>>class C2(object):
>>  def f(self):
>>return X['field']
>>
>> O1 = C1()
>> O1['field'] = 1
>> O2 = O1.C2()
>> print(O2.f())
>
>
> I prefer to *feed* the child to the parent or vice versa.

Congrats, this ranks on my list of "creative people who sound like
psycho murderers". Digital artists and cooks tend to rank fairly
highly on that list.

> class C1(object):
> def __init__(self):
> self.child = None
> class C2(object):
> def __init__(self, parent=None):
> self.parent = parent

The trouble with this is that there's fully-constructed objects with
no parent-child relationships. Why should you have a two-step
construction process? It makes a LOT more sense to simply require a
parent on construction, rather than feeding one to the other in a
post-construction assignment. And if you remove the default here, your
suggestion isn't materially different from what's already been posted.

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


Re: Accessing parent objects

2018-03-25 Thread D'Arcy Cain
On 03/25/2018 04:37 AM, Jugurtha Hadjar wrote:
> On 03/24/2018 07:14 PM, D'Arcy Cain wrote:
>> class C1(dict):
>>    class C2(object):
>>  def f(self):
>>    return X['field']
>>
>> O1 = C1()
>> O1['field'] = 1
>> O2 = O1.C2()
>> print(O2.f())
> 
> I prefer to *feed* the child to the parent or vice versa. Simplifies
> things like testing.

That was my original solution but it seems clumsy.

O2 = O1.C2(O1)

IOW passing the parent object to the child class.  It just seems like
there should be some way to access the parent object in C2.

> Something like this:
> 
> class C1(object):
...
> class C2(object):
>     def __init__(self, parent=None):
> self.parent = parent

Perhaps your email client is collapsing leading spaces but that isn't
what I wrote.  The C2 class is supposed to be a member of C1.  That's
why I called it as O1.C2() instead of just C2().  I was hoping that by
doing so that the data in O1 would somehow be available without having
to explicitly pass it as an argument.

However, I would have made the parameter required.  I don't see the
point of calling another method to add it in later.  Of course, if I do
that there's no point in making C2 part of C1.  What you wrote would be
just fine and obvious.

-- 
D'Arcy J.M. Cain
Vybe Networks Inc.
http://www.VybeNetworks.com/
IM:[email protected] VoIP: sip:[email protected]
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Accessing parent objects

2018-03-25 Thread D'Arcy Cain
On 03/25/2018 05:10 AM, Jugurtha Hadjar wrote:
>     print("I am {self.__class__.__name__} foo".format(self=self))

Unrelated to the original issue but why not one of the following?

print("I am {0.__class__.__name__} foo".format(self))
print(f"I am {self.__class__.__name__} foo")

-- 
D'Arcy J.M. Cain
Vybe Networks Inc.
http://www.VybeNetworks.com/
IM:[email protected] VoIP: sip:[email protected]
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Accessing parent objects

2018-03-25 Thread D'Arcy Cain
On 03/24/2018 06:54 PM, Steven D'Aprano wrote:
>> On Saturday, March 24, 2018 at 1:20:24 PM UTC-5, D'Arcy Cain wrote:
>>> I tried various forms of super() but that didn't seem to work.
> 
> Define "doesn't see to work".

It accesses the parent class.  I want to access the parent object.

-- 
D'Arcy J.M. Cain
System Administrator, Vex.Net
http://www.Vex.Net/ IM:[email protected]
VoIP: sip:[email protected]
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Accessing parent objects

2018-03-25 Thread Jugurtha Hadjar


On 03/25/2018 11:17 AM, Chris Angelico wrote:

On Sun, Mar 25, 2018 at 8:37 PM, Jugurtha Hadjar
 wrote:

On 03/24/2018 07:14 PM, D'Arcy Cain wrote:

class C1(dict):
class C2(object):
  def f(self):
return X['field']

O1 = C1()
O1['field'] = 1
O2 = O1.C2()
print(O2.f())


I prefer to *feed* the child to the parent or vice versa.

Congrats, this ranks on my list of "creative people who sound like
psycho murderers". Digital artists and cooks tend to rank fairly
highly on that list.


Given that without prior knowledge, Python may suggest a satirical show 
or a huge snake, I'm right at home as either creative or a psycho.



class C1(object):
 def __init__(self):
 self.child = None
class C2(object):
 def __init__(self, parent=None):
 self.parent = parent

The trouble with this is that there's fully-constructed objects with
no parent-child relationships. Why should you have a two-step
construction process? It makes a LOT more sense to simply require a
parent on construction, rather than feeding one to the other in a
post-construction assignment. And if you remove the default here, your
suggestion isn't materially different from what's already been posted.



Right, I see.. What do you think about something like this:

<--->

class C2(object):
    def __init__(self, parent=None):
    self.parent = parent

    def foo(self):
    print("I am {self.__class__.__name__} foo".format(self=self))
    self.parent.foo()


class C1(object):
    def __init__(self, child_class=None):
    self.child = child_class(parent=self)

    def foo(self):
    print("I am {self.__class__.__name__} foo".format(self=self))

c1 = C1(child_class=C2)
c1.child.foo()  # I am C2 foo
    # I am C1 foo

<>


Check my logic: The reason I'm going through these contortions is to 
allow the user to choose which child class to use instead of hard coding 
C2 inside C1, hence the psycho feeding/injecting of C2 in C1. I can 
delay making a choice and I can even postpone it to run-time (say I have 
a web-page with a menu that asks which child class I want to use, I can 
select C2, or C1 and I'll have the instance created with my choice).


Does this make sense and is there a more succinct way to do it this way?

--
~ Jugurtha Hadjar,

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


Re: Accessing parent objects

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 21:17:59 +1100, Chris Angelico wrote:

> On Sun, Mar 25, 2018 at 8:37 PM, Jugurtha Hadjar
>  wrote:
[...]
>> I prefer to *feed* the child to the parent or vice versa.
> 
> Congrats, this ranks on my list of "creative people who sound like
> psycho murderers". Digital artists and cooks tend to rank fairly highly
> on that list.

:-)

>> class C1(object):
>> def __init__(self):
>> self.child = None
>> class C2(object):
>> def __init__(self, parent=None):
>> self.parent = parent
> 
> The trouble with this is that there's fully-constructed objects with no
> parent-child relationships. Why should you have a two-step construction
> process? 

Such a two-step construction process is normally called "dependency 
injection", and it's really useful.

https://martinfowler.com/articles/injection.html

Instead of class C2 controlling what its parent is:

class C2:
def __init__(self):
self.parent = C1()

the caller decides what parent to use. Provided the parent provides the 
same interface as C1, you can use any duck-type you like.

The thing is, we use dependency injection in Python all the time. We just 
don't call it that! We normally write things like:

class Spam:
def __init__(self, queue=None):
if queue is None:
queue = Queue()
self.queue = queue

and so we get the best of both worlds: the ability to inject the queue we 
want when we need to, and the freedom to not bother when we don't. This 
is such second nature that we don't even think that what we're doing has 
a fancy OOP design pattern name that Java programmers stress over.

And because we duck-type, we don't care if queue is a real queue, or just 
something that has all the queue methods we require.


> It makes a LOT more sense to simply require a parent on
> construction, rather than feeding one to the other in a
> post-construction assignment.

I tend to agree... but not everyone in the OOP world does. Quoting from 
Wikipedia:

There are at least three ways an object can receive a reference
to an external module:

- constructor injection: the dependencies are provided through
  a class constructor.
- setter injection: the client exposes a setter method that the
  injector uses to inject the dependency.
- interface injection: the dependency provides an injector method
  that will inject the dependency into any client passed to it.

https://en.wikipedia.org/wiki/Dependency_injection



-- 
Steve

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


Re: Accessing parent objects

2018-03-25 Thread Jugurtha Hadjar
Erratum: "I can select C2, or C3 and I'll have the instance created with 
my choice"




--
~ Jugurtha Hadjar,

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


Re: Accessing parent objects

2018-03-25 Thread Rick Johnson
On Saturday, March 24, 2018 at 11:31:38 PM UTC-5, Steven D'Aprano wrote:
> On Sat, 24 Mar 2018 20:08:47 -0700, Rick Johnson wrote:
[...]
> >
> > the inconsistency of using super _outside_ of Tkinter code
> > whilst simultaneously using explicit inheritance _inside_
> > Tkinter code was quite frankly, disturbing to me.
> 
> "A foolish consistency is the hobgoblin of little minds,
> adored by little statesmen and philosophers and divines."
> >
> > Thus, i chose to abandon super altogether.
> 
> Baby, bathwater.

I'm afraid quote-mining won't help your argument. There is
nothing wrong about choosing consistency over inconsistency.
But what i find more troubling, is that you seem to
misunderstand the significance of Emerson's famous "foolish
consistency" quip; which became the spearhead of a more
broad treatise warning us of the dangers inherent in
orthodoxy. And while Emerson's warning can be applied widely
to personal philosophy, the warning applies only very
narrowly to the realm of programming; which forces us to use
certain structures and forms that are beyond our control.
For example, a Python programmer can no more define a class
with the keyword "object" than he/she could define a
function with the keyword "function", or import a module
from a package using colons, exclamation-marks and
ampersands:

>>> object Foo():

SyntaxError: invalid syntax

>>> function bar():

SyntaxError: invalid syntax

>>> from foolish:consistency! import &platitudes
SyntaxError: invalid syntax

Python dictates that we follow certain well-defined rules.
But following these rules is no evidence of a foolish
consistency, much less an orthodoxy. For example, here is a
quote from PEP8, which underscores my position and explains
the significance of the "foolish consistency" quip:

"""
A Foolish Consistency is the Hobgoblin of Little Minds
-

One of Guido's key insights is that code is read much more
often than it is written. The guidelines provided here are
intended to improve the readability of code and make it
consistent across the wide spectrum of Python code. As PEP
20 says, "Readability counts".

A style guide is about consistency. Consistency with this
style guide is important. Consistency within a project is
more important. Consistency within one module or function is
the most important.
"""

Okay. So if there is one lesson to take away from this
quote, the lesson is that readability is important, and
futhermore, that readability is highly dependant on
maintaining a consistent presentation/form of source code
(aka: consistency).

Thus, a sporadic implementation of super() in my source code
would violate the spirit of PEP8. And although i freely
admit that super() is technically the correct way to go,
it's not my fault that Python2's Tkinter is incompatible
with super, and so my decision to maintain consistency --
and thus readability -- perfectly aligns with the standards
of PEP8. Thus, it is Pythonic.

So yes, I chose the path of _consistency_, for which the
natural side effect is _readability_, and Steven, there is
absolutely nothing "foolish" about that!

> > But when i make the switch to Python4000, i will probably
> > adopt super at that time, along with all the other fully
> > matured goodies.
> 
> So, having avoided the first unstable compatibility-
> breaking version, Python 3000, you're going to wait until
> the next hypothetical unstable, compatibility-breaking
> version before upgrading?

Yes. But there's more "method to my madness" than meets your
eye. And although you don't know it yet, you're about to
provide the justification for my delay using your very own
words 

(so stay tuned, this is going to be fun!)

(well, perhaps not for you!)

> Python 3 is now six point releases in (and very soon to
> have a seventh, 3.7 being in beta as we speak). It is
> stable, feature-rich, and a joy to work in. As well as a
> heap of great new features, there have been a metric tonne
> of performance improvements, making Python 3 faster than
> 2.7 for many tasks, e.g.
> 
> [snip: link]
> 
> Python 4 is not going to be a massively compatibility-
> breaking change like Python 3 was,

Exactly! Thus the reason i am avoiding Python3 like the
plague.

> and version 4 is likely about 5 or 6 years away. 

That's fine. I'm in no hurry.

> Some hypothetical "Python 4000", or more likely "5000", is
> at least a decade away, if it ever occurs again. (Which it
> probably won't.)

Which is it? "5 or 6 years" or "a decade"? Make up your
mind, would ya?

Even if an official version number "4" is not offered, and
Python3 is the last version of Python, at some point the
churn of Python3 will slow, and thus, in sprit it will
become the stable equivalent of Python4. So sorry to
disappoint you Steven, but either way, i win. O:-)

> In the meantime, Python 2.7 will fall out of extended

Re: Accessing parent objects

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 06:11:53 -0500, D'Arcy Cain wrote:

> On 03/24/2018 06:54 PM, Steven D'Aprano wrote:
>>> On Saturday, March 24, 2018 at 1:20:24 PM UTC-5, D'Arcy Cain wrote:
 I tried various forms of super() but that didn't seem to work.
>> 
>> Define "doesn't see to work".
> 
> It accesses the parent class.  I want to access the parent object.

Ah. Well, no wonder it doesn't work: you're confusing the OO inheritance 
concept of "parent" (a superclass) with whatever relationship you have 
between one instance and another instance. Just because they share the 
same name doesn't make them the same concept.


-- 
Steve

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


Re: Accessing parent objects

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 05:57:40 -0500, D'Arcy Cain wrote:

> That was my original solution but it seems clumsy.
> 
> O2 = O1.C2(O1)

Are you intentionally trying to melt my brain with horribly obfuscated, 
meaningless names? If so, you've succeeded admirably millennium hand and 
shrimp buggarit.

:-)


> IOW passing the parent object to the child class.  It just seems like
> there should be some way to access the parent object in C2.

Of course there's a way, it's just tricky. There's just no *automatic* 
way.

Classes are no different to any other object: objects only know what they 
hold a reference to, not what holds a reference to them. Given:

class Spam:
eggs = "Wibble"

the class Spam knows about the string "Wibble", but the string has no way 
of knowing about Spam. The same applies to nested classes:

class Spam:
class Eggs:
pass


There's no difference here, except that unlike strings, classes can hold 
references to other objects. So we can inject a reference to Spam to 
Eggs, but unfortunately we can't do from inside Spam, since it doesn't 
exist as yet!

class Spam:
class Eggs:
pass
Eggs.owner = Spam  # NameError


But we can do it from the outside once the class is built:

Spam.Eggs.owner = Spam



Some possible solutions:

- use a class decorator or a metaclass

- do the injection in the Spam __init__ method:

class Spam:
class Eggs:
pass
def __init__(self):
self.egg = egg = type(self).Eggs()
egg.owner = self


Possibly use a Weak Reference instead of a regular reference.




-- 
Steve

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


Re: Entering a very large number

2018-03-25 Thread bartc

On 25/03/2018 02:47, Steven D'Aprano wrote:

On Sun, 25 Mar 2018 00:05:56 +0100, Peter J. Holzer wrote:

[...]

yes, good idea


Not if you want to avoid that string to int conversion (as you stated).

That is still there, but in addition you now split the string into a
list and then join the list into a different string.


I'm glad I wasn't the only one who spotted that.

There's something very curious about somebody worried about efficiency
choosing a *less* efficient solution than what they started with. To
quote W.A. Wulf:

"More computing sins are committed in the name of efficiency (without
necessarily achieving it) than for any other single reason — including
blind stupidity."

As Donald Knuth observed:

"We should forget about small efficiencies, say about 97% of the time:
premature optimization is the root of all evil."

The Original Poster (OP) is concerned about saving, what, a tenth of a
microsecond in total? Hardly seems worth the effort, especially if you're
going to end up with something even slower.


Using CPython on my machine, doing a string to int conversion that 
specific number took 200 times as long as doing a normal assignment.


That conversion took 4 microseconds.

Not significant if it's only done once. But it might be executed a 
million times.


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


Re: Entering a very large number

2018-03-25 Thread Christian Gollwitzer

Am 25.03.18 um 14:32 schrieb bartc:
Using CPython on my machine, doing a string to int conversion that 
specific number took 200 times as long as doing a normal assignment.


That conversion took 4 microseconds.

Not significant if it's only done once. But it might be executed a 
million times.


Honestly, why should it be executed a million times? Do you have a 
million different 400 digit numbers as constants in your code? If so, I 
suggest to store them in a database file accompanied with the code.


If there are few different only, then don't do the conversion a million 
times. Convert them at module initialization and assign them to a global 
variable.


Christian

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


Re: Accessing parent objects

2018-03-25 Thread Ian Kelly
On Sun, Mar 25, 2018 at 5:46 AM, Steven D'Aprano
 wrote:
> On Sun, 25 Mar 2018 06:11:53 -0500, D'Arcy Cain wrote:
>> It accesses the parent class.  I want to access the parent object.
>
> Ah. Well, no wonder it doesn't work: you're confusing the OO inheritance
> concept of "parent" (a superclass) with whatever relationship you have
> between one instance and another instance. Just because they share the
> same name doesn't make them the same concept.

No, he's merely confusing the concept of nested classes in Python with
nested classes in Java, which actually supports this magic.

To the OP: Python isn't Java. Nested classes in Python work like
"static" nested classes in Java.
-- 
https://mail.python.org/mailman/listinfo/python-list


Ruby parens-free function calls [was Re: Accessing parent objects]

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 04:49:21 -0700, Rick Johnson wrote:

>> - with no arguments, using the parenthesis-free syntax,
>>   Ruby automagically forwards the same arguments to the (single)
>>   parent;
> 
> Which is merely a natural result of Ruby's function/method call syntax.
> Not allowing a parenthesis-free super call would not only be
> inconsistent, it would be foolishly inconsistent.

I never said anything about not allowing it. But since you've gone on the 
defence about parens-free function calls, how is this for "consistency" 
in Ruby?

[steve@ando ruby]$ ruby ws-example.rb
a + b => 7
a+b   => 7
a+ b  => 7
a +b  => 3


Here's the source code:

# --- cut ---
def a(x=4)
x+2
end

b = 1
print "a + b => ", (a + b), "\n"
print "a+b   => ", (a+b), "\n"
print "a+ b  => ", (a+ b), "\n"
print "a +b  => ", (a +b), "\n"
# --- cut ---



>> So there's weird magic going on where `super` and `super()` both call
>> the method but with different arguments. Ewww.
> 
> It's only weird because you are judging through a Python lens. Ruby is
> not Python. And Python is not Ruby.

No, its weird because in *both cases* there are no arguments given, but 
in one case there are no arguments passed, but in the other case, some 
unknown number of invisible arguments are passed.

Consider a bunch of Ruby function calls:

f()  # calls f with no arguments
f# calls f with no arguments
foo()# calls foo with no arguments
foo  # calls foo with no arguments
bar()# calls bar with no arguments
bar  # calls bar with no arguments
super()  # calls the superclass method with no arguments
super# MAGIC HAPPENS! calls the superclass method with
   some unknown number of arguments!


If you want to argue that's a useful feature, okay, I'll give you the 
benefit of the doubt. But useful or not, it's still weird and surprising. 
And deeply, fundamentally inconsistent.


-- 
Steve

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


Re: Accessing parent objects

2018-03-25 Thread Terry Reedy

On 3/25/2018 7:42 AM, Jugurtha Hadjar wrote:


class C2(object):
     def __init__(self, parent=None):
     self.parent = parent


Since parent is required, it should not be optional.


     def foo(self):
     print("I am {self.__class__.__name__} foo".format(self=self))
     self.parent.foo()


None.foo will raise AttributeError.


class C1(object):
     def __init__(self, child_class=None):
     self.child = child_class(parent=self)


Ditto.  None() will raise TypeError

If your intent is to force passing parent/child_class by name rather 
than by position, use *, as in

def __init__(self, *, child_class):



     def foo(self):
     print("I am {self.__class__.__name__} foo".format(self=self))

c1 = C1(child_class=C2)
c1.child.foo()  # I am C2 foo
     # I am C1 foo



--
Terry Jan Reedy


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


Multiple Inheritance [was Re: Accessing parent objects]

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 04:49:21 -0700, Rick Johnson wrote:

[...]
> Ruby is fundamentally _opposed_ to the idea of multiple inheritance  --
> as MI is rife with issues (technical, practical, and intuitive in
> nature) and thus, not a wise solution -- but you would have known that
> Steven

I know that many people consider multiple inheritance (MI) to be a bad 
idea. I would even agree with them that using MI is often over-kill, 
difficult to get right, and doesn't really scale well to large class 
hierarchies. (But then, what does?)

But sometimes MI is the easiest way to get the job done.

Michele Simionato has spent a *lot* of time writing about the limitations 
of MI, and alternatives such as mixins and traits. See his blog on 
Artima, a good place to start is here:

https://www.artima.com/weblogs/viewpost.jsp?thread=246488

In Ruby, mixins are a special kind of thing; in Python, mixins are merely 
implemented as ordinary classes, using multiple inheritance. There are 
pros and cons to each approach.

Actually, in Ruby, mixins are implemented using inheritance too, despite 
using distinct keywords.

https://andrewbrookins.com/technology/mixins-in-python-and-ruby-compared/



[...]
>> which is exactly when super() is most important.
> 
> Your assertion presupposes that MI is the only way to solve the problem
> that MI proposes to solve.

I don't understand your reasoning. All I'm saying is that if your langage 
doesn't support MI, then super doesn't gain you much except to save a few 
keystrokes.

Where super is really necessary is when your language supports MI, and 
specifically MI where the class hierarchy can form a diamond shape.


> And it is not only the Ruby folks who find MI
> to be woefully inadequate. The impracticality of MI has been the subject
> of much debate.

Indeed. And the correct word to use is *debate*.



-- 
Steve

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


Re: Accessing parent objects

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 08:09:02 -0600, Ian Kelly wrote:

> On Sun, Mar 25, 2018 at 5:46 AM, Steven D'Aprano
>  wrote:
>> On Sun, 25 Mar 2018 06:11:53 -0500, D'Arcy Cain wrote:
>>> It accesses the parent class.  I want to access the parent object.
>>
>> Ah. Well, no wonder it doesn't work: you're confusing the OO
>> inheritance concept of "parent" (a superclass) with whatever
>> relationship you have between one instance and another instance. Just
>> because they share the same name doesn't make them the same concept.
> 
> No, he's merely confusing the concept of nested classes in Python with
> nested classes in Java, which actually supports this magic.
> 
> To the OP: Python isn't Java. Nested classes in Python work like
> "static" nested classes in Java.


TIL, thanks.


(I'm not sure exactly what I've learned, but I learned *something* about 
nested classes in Java.)

-- 
Steve

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


Re: Accessing parent objects

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 04:49:21 -0700, Rick Johnson wrote:

> On Saturday, March 24, 2018 at 11:31:38 PM UTC-5, Steven D'Aprano wrote:
[...]
>> "A foolish consistency is the hobgoblin of little minds, adored by
>> little statesmen and philosophers and divines."
>> >
>> > Thus, i chose to abandon super altogether.
>> 
>> Baby, bathwater.
> 
> I'm afraid quote-mining won't help your argument. There is nothing wrong
> about choosing consistency over inconsistency.

Depends on whether it is a foolish consistency or a sensible consistency.

[...]
> Python dictates that we follow certain well-defined rules.

Indeed. And one of those "rules" is that super is the right way to handle 
inheritance in a class. Unfortunately, for historical reasons, old-style 
Python 1 classes don't support super. So I sympathise with your plight in 
regards to tkinter classes.

(However that sympathy is heavily dissipated by the knowledge that this 
is a self-inflicted wound, due to your stubborn refusal to use Python 3.)

But refusing to use super in modern, new-style classes that don't have 
anything to do with tkinter is precisely the sort of *foolish* 
consistency that Emerson was warning about.

Your position is equivalent to noting that tuples don't have a sort 
method, and so "for the sake of consistency" refusing to use list.sort() 
even when you *know* you have a list.

Or, and perhaps even more relevant, because *some* functions don't 
support keyword arguments:

len(obj=arg)  # TypeError

for the sake of consistency you must never use keyword arguments even 
though your code would be improved by it:

function_with_many_optional_arguments(
None, None, None, None, None, None, 
None, None, None, None, arg
)


[...]
> Thus, a sporadic implementation of super() in my source code would
> violate the spirit of PEP8.

That's the sort of dubious reading of PEP 8 that Guido was warning 
against in his quote from Emerson.

Just because for technical reasons class Foo cannot use super, does not 
mean that you should never use super in any other class for the sake of 
"consistency". Consistency within a single class is more important than a 
foolish consistency across all classes.

Especially since by your own admission, you are *giving up correctness* 
in order to buy "consistency":

> And although i freely admit that super() is
> technically the correct way to go


[...]
>> So, having avoided the first unstable compatibility- breaking version,
>> Python 3000, you're going to wait until the next hypothetical unstable,
>> compatibility-breaking version before upgrading?
> 
> Yes. But there's more "method to my madness" than meets your eye. And
> although you don't know it yet, you're about to provide the
> justification for my delay using your very own words
[...]

>> Python 4 is not going to be a massively compatibility-breaking change
>> like Python 3 was,
> 
> Exactly! Thus the reason i am avoiding Python3 like the plague.

Er... you do realise that Python 4.x is going to keep compatibility with 
Python 3.x? Whatever reasons you think you have for avoiding Python 3, 
those exact same reasons will apply to Python 4.

In fact, as Python continues to add more features, the distance between 
2.7 and the latest version is just going to continue growing.

If you're holding out under some fantasy that Python 4 is going to undo 
all the new features and become a de facto version 2.8, you are going to 
be very disappointed.



>> and version 4 is likely about 5 or 6 years away.
> 
> That's fine. I'm in no hurry.
> 
>> Some hypothetical "Python 4000", or more likely "5000", is at least a
>> decade away, if it ever occurs again. (Which it probably won't.)
> 
> Which is it? "5 or 6 years" or "a decade"? Make up your mind, would ya?

The moniker "Python X-thousand" (Python 3000, 4000, 5000...) is usually 
understood to mean a backwards-compatibility breaking version. Since 
Python 4 will *not* be such a version, what you are calling 4000 is 
better called "5000". If it even exists at all, it will be in the distant 
future, long after 4.0 and 4.1 are memories: my estimate is that nobody 
in the Python community will even consider another such major 
compatibility break until 4.7 or 4.9.

And even that is a very slim chance.


> Even if an official version number "4" is not offered, and Python3 is
> the last version of Python, at some point the churn of Python3 will
> slow, and thus, in sprit it will become the stable equivalent of
> Python4. So sorry to disappoint you Steven, but either way, i win. O:-)

Do you know what they call programming languages that stop evolving?

"Dead."



-- 
Steve

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


Re: Entering a very large number

2018-03-25 Thread Joe Pfeiffer
ast  writes:

> Hi
>
> I found this way to put a large number in
> a variable.
>
> C = int(
> "28871482380507712126714295971303939919776094592797"
> "22700926516024197432303799152733116328983144639225"
> "94197780311092934965557841894944174093380561511397"
> "4215424169339729054237110027510420801349667317"
> "5515285922696291677532547505856101949404200039"
> "90443211677661994962953925045269871932907037356403"
> "22737012784538991261203092448414947289768854060249"
> "76768122077071687938121709811322297802059565867")
>
> It works but is it not optimal since there is a
> string to int conversion.
>
> I was not able to put an integer directly because
> character '\' for line cut doesnt work inside an
> integer
>
> C = \
> 28871482380507712126714295971303939919776094592797\
> 22700926516024197432303799152733116328983144639225\
> ...
> 76768122077071687938121709811322297802059565867

After following the thread for a while...  you will, of course, simply
have to do a string to int conversion no matter what approach you take
to writing it.  The number is a string of digits; it has to be converted
to the internal representation.  Even if you write

C = 
28871482380507712126714295971303939919776094592797227009265160241974323037991527331163289831446392259419778031109293496555784189494417409338056151139742154241693397290542371100275104208013496673175515285922696291677532547505856101949404200039904432116776619949629539250452698719329070373564032273701278453899126120309244841494728976885406024976768122077071687938121709811322297802059565867

the conversion happens.  Of all the variations people have proposed to
try to make the number more readable, the one you started with above
seems clearest to me.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Accessing parent objects

2018-03-25 Thread Jugurtha Hadjar


On 03/25/2018 03:25 PM, Terry Reedy wrote:

On 3/25/2018 7:42 AM, Jugurtha Hadjar wrote:


class C2(object):
 def __init__(self, parent=None):
 self.parent = parent


Since parent is required, it should not be optional.



You can still call it the way you'd call it if it were a positional 
argument.


i.e:

def foo(keyword_argument=None):
    print(keyword_argument)

foo(3)
foo(keyword_argument=3)


Just because it's a keyword argument doesn't mean it's not required. I 
could have provided a default using `self.parent = parent or C2`, but I 
didn't want to assume C2 was defined in that namespace and wanted to 
give as generic a code as I could.


Furthermore, the only case I'd use a positional argument is if I were 
100% certain the code will not change, which I'm not. Plus when the API 
will change (and it will), it will be harder to deal with it that if it 
were a keyword argument. If you change the order you'd have to change 
the whole codebase where the class/function is instantiated/called, 
whereas if you use a keyword argument, you could just catch the old way 
call, issue a deprecation warning, then route the call for the new way call.


What benefit does the positional argument provide?




 def foo(self):
 print("I am {self.__class__.__name__} foo".format(self=self))
 self.parent.foo()


None.foo will raise AttributeError.



Right.. As I said, I tried to assume as little as possible about OP's 
code and namespace. Didn't want to include C1 in __init__ signature 
because I wasn't sure it was available in the namespace.


It is easy to address, though:

Example A:

class C2(object):
 def __init__(self, parent=C2):
 self.parent = parent

Example B:

class C2(object):
    def __init__(self, parent=None):
    self.parent = parent or C2



Furthermore, having a positional argument will not save us. We can still 
break the code if we do the following:


class C2(object):
    def __init__(self, parent):
    self.parent = parent
    def foo(self):
    self.parent.foo()

c1 = C1()
c2 = C2(None)
c2.foo()

Making it positional didn't fix our wickedness.



class C1(object):
 def __init__(self, child_class=None):
 self.child = child_class(parent=self)


Ditto.  None() will raise TypeError



Ditto, so would it if your C2 instance is None for whatever reason.

If your intent is to force passing parent/child_class by name rather 
than by position, use *, as in

    def __init__(self, *, child_class):



 def foo(self):
 print("I am {self.__class__.__name__} foo".format(self=self))

c1 = C1(child_class=C2)
c1.child.foo()  # I am C2 foo
 # I am C1 foo





I don't want to force using named params vs keyword params, or I would 
have used the asterisk in the first place. I write that code, as I said, 
because I have zero to gain from using a positional argument (which 
using keyword arguments behaves the same way as far as I'm concerned if 
I call the params in order), and a lot to lose: when I change the API, 
I'd have to change the whole parts where I instantiate the class or call 
the method.


Suppose I have a class like this:

class Foo(object):
    def __init__(self, name, height, address):
    self.name = name
    self.height = height
    self.address = address

Suppose I then want to change it to:


class Foo(object):
    def __init__(self, status, name, address, height):
    self.status = status
    self.name = name
    self.height = height
    self.address = address


This would totally screw up other parts of the code where the class is 
used. I tend to use positional arguments when it's *way* unlikely the 
code will ever change, and even then I probably wouldn't.


--
~ Jugurtha Hadjar,

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


Re: Accessing parent objects

2018-03-25 Thread Jugurtha Hadjar

On 03/25/2018 11:57 AM, D'Arcy Cain wrote:



Something like this:

class C1(object):

...

class C2(object):
     def __init__(self, parent=None):
 self.parent = parent

Perhaps your email client is collapsing leading spaces but that isn't
what I wrote.  The C2 class is supposed to be a member of C1.  That's
why I called it as O1.C2() instead of just C2().  I was hoping that by
doing so that the data in O1 would somehow be available without having
to explicitly pass it as an argument.


It's not my mail client, this was my proposed code in which C2 is 
defined *outside* of C1, then you inject one or the other (can't decide 
for you as it depends on what you're trying to do).

In other words, it's not an indentation error.


However, I would have made the parameter required.  I don't see the
point of calling another method to add it in later.  Of course, if I do
that there's no point in making C2 part of C1.  What you wrote would be
just fine and obvious.



I tend to use keyword arguments a lot because it gives me a lot of 
freedom. Just a perk: I can do things like change the API and I'd only 
have to catch the call, issue a deprecation warning, and then use the 
new API instead of having the code be rigid.


--
~ Jugurtha Hadjar,

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


Re: Entering a very large number

2018-03-25 Thread bartc

On 25/03/2018 15:01, Christian Gollwitzer wrote:

Am 25.03.18 um 14:32 schrieb bartc:
Using CPython on my machine, doing a string to int conversion that 
specific number took 200 times as long as doing a normal assignment.


That conversion took 4 microseconds.

Not significant if it's only done once. But it might be executed a 
million times.


Honestly, why should it be executed a million times?


Because it's inside a function that is called a million times?

 Do you have a
million different 400 digit numbers as constants in your code? If so, I 
suggest to store them in a database file accompanied with the code.


If there are few different only, then don't do the conversion a million 
times. Convert them at module initialization and assign them to a global 
variable.


That's just another workaround. You don't really want the global 
namespace polluted with names that belong inside functions. And you 
might not want to do all that initialisation on behalf of hundreds of 
functions that may or may not be called. Neither do you want the code at 
module level to be cluttered with all these giant constants.


The real problem is in writing a very long constant that doesn't 
comfortably fit on one screen line, and where the editor used doesn't 
offer any help (in displaying on multiple lines) and neither does the 
language.


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


Re: Entering a very large number

2018-03-25 Thread Fran Litterio

On 3/25/2018 10:53 AM, Joe Pfeiffer wrote:

After following the thread for a while...  you will, of course, simply
have to do a string to int conversion no matter what approach you take
to writing it.  The number is a string of digits; it has to be converted
to the internal representation.  Even if you write

C = 
28871482380507712126714295971303939919776094592797227009265160241974323037991527331163289831446392259419778031109293496555784189494417409338056151139742154241693397290542371100275104208013496673175515285922696291677532547505856101949404200039904432116776619949629539250452698719329070373564032273701278453899126120309244841494728976885406024976768122077071687938121709811322297802059565867

the conversion happens.


But doesn't that string-to-int conversion happen at compile-time not 
run-time?

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


Re: Entering a very large number

2018-03-25 Thread bartc

On 25/03/2018 15:53, Joe Pfeiffer wrote:

ast  writes:



C = int(
"28871482380507712126714295971303939919776094592797"
"22700926516024197432303799152733116328983144639225"
"94197780311092934965557841894944174093380561511397"
"4215424169339729054237110027510420801349667317"
"5515285922696291677532547505856101949404200039"
"90443211677661994962953925045269871932907037356403"
"22737012784538991261203092448414947289768854060249"
"76768122077071687938121709811322297802059565867")



After following the thread for a while...  you will, of course, simply
have to do a string to int conversion no matter what approach you take
to writing it.


What, even with you write this:

  C = 12

?


The number is a string of digits; it has to be converted
to the internal representation.


Which is usually done by a compiler, and it will only do it once not 
each time the line is encountered in a running program. (Although a 
compiler will also do the conversion when the line is never executed!)



Even if you write

C = 
28871482380507712126714295971303939919776094592797227009265160241974323037991527331163289831446392259419778031109293496555784189494417409338056151139742154241693397290542371100275104208013496673175515285922696291677532547505856101949404200039904432116776619949629539250452698719329070373564032273701278453899126120309244841494728976885406024976768122077071687938121709811322297802059565867

the conversion happens.


But not at runtime.

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


Re: Accessing parent objects

2018-03-25 Thread Ian Kelly
On Sun, Mar 25, 2018 at 9:01 AM, Jugurtha Hadjar
 wrote:
>
> On 03/25/2018 03:25 PM, Terry Reedy wrote:
>>
>> On 3/25/2018 7:42 AM, Jugurtha Hadjar wrote:
>>
>>> class C2(object):
>>>  def __init__(self, parent=None):
>>>  self.parent = parent
>>
>>
>> Since parent is required, it should not be optional.
>>
>
> You can still call it the way you'd call it if it were a positional
> argument.
>
> i.e:
>
> def foo(keyword_argument=None):
> print(keyword_argument)
>
> foo(3)
> foo(keyword_argument=3)
>
>
> Just because it's a keyword argument doesn't mean it's not required. I could
> have provided a default using `self.parent = parent or C2`, but I didn't
> want to assume C2 was defined in that namespace and wanted to give as
> generic a code as I could.

You misunderstand what keyword arguments are. Giving the argument a
default does not make it a keyword argument. Passing the argument with
keyword syntax is what makes it a keyword argument. It happens at the
call site, not when it's defined (with the exception of keyword-only
arguments, which this is not).

This function takes an argument x either by position or by keyword:

def foo(x): pass

This function also takes an argument x either by position or by keyword:

def foo(x=None): pass

The only difference is that the latter makes the argument optional by
assigning a default, whereas the former requires it.

The point is, if the argument is effectively required and doesn't have
a sensible default, then don't make it optional. You can still pass it
by keyword if that's what you want.
-- 
https://mail.python.org/mailman/listinfo/python-list


A question related to the PYTHONPATH

2018-03-25 Thread adrien oyono
Hello everyone,

This is my first email to the python list, I'll try my best to do it well.

TL;DR

I have recently read the documentation about how imports work on python,
and I was wondering why, when you execute a python file, the current
directory is not added by default to the PYTHONPATH ?

Extended:

Let's assume we have this directory structure for a python package:

$ tree A
A
├── B1
│   ├── b1.py
│   ├── C1
│   │   ├── c1_1.py
│   │   ├── c1.py
│   │   └── __init__.py
│   └── __init__.py
├── B2
│   ├── b2.py
│   ├── C2
│   │   ├── c2.py
│   │   └── __init__.py
│   └── __init__.py
├── __init__.py
└── toto.py

4 directories, 11 files


with the file A/B2/C2/c2.py content being:

import sys
print(sys.path)

import A

from A.B2.b2 import PLOP
from A.B1.C1.c1 import TOTO

print(TOTO)


If I do, from the top level directory containing the package A:

$ python A/B2/C2/c2.py

I get an :

['/tmp/A/B2/C2', '/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/home/cris/.local/lib/python2.7/site-packages',
'/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-
packages/gtk-2.0']
Traceback (most recent call last):
  File "A/B2/C2/c2.py", line 9, in 
import A
ImportError: No module named A

Which is normal according to the documentation of Python 2
(https://docs.python.org/2/tutorial/modules.html#the-module-search-path):

When a module named spam is imported, the interpreter first searches for a
> built-in module with that name. If not found, it then searches for a file
> named spam.py in a list of directories given by the variable sys.path
> . sys.path
>  is initialized from
> these locations:
>
>- the directory containing the input script (or the current directory).
>- PYTHONPATH
> (a
>list of directory names, with the same syntax as the shell variable
>PATH).
>- the installation-dependent default.
>
> After initialization, Python programs can modify sys.path
> . The directory
> containing the script being run is placed at the beginning of the search
> path, ahead of the standard library path. This means that scripts in that
> directory will be loaded instead of modules of the same name in the library
> directory. This is an error unless the replacement is intended. See section 
> Standard
> Modules
>  for
> more information.
>

Meanwhile when I do:

$ python -m A.B2.C2.c2

I get the script running correctly:

['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/home/cris/.local/lib/python2.7/site-packages',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages/PILcompat',
'/usr/lib/python2.7/dist-packages/gtk-2.0']
42

An empty string is now pre-pended to the value of sys.path, which means, if
I correctly interpret the documentation of Python 3, that the current
directory is added to the PYTHONPATH (https://docs.python.org/3/
reference/import.html#path-entry-finders):

The current working directory – denoted by an empty string – is handled
> slightly differently from other entries on sys.path
> . First, if the
> current working directory is found to not exist, no value is stored in
> sys.path_importer_cache
> .
> Second, the value for the current working directory is looked up fresh for
> each module lookup. Third, the path used for sys.path_importer_cache
>  and
> returned by importlib.machinery.PathFinder.find_spec()
> 
> will be the actual current working directory and not the empty string.
>


What I am interested in is what is the reason of this difference ?


P.S.:

   - My english may suck a bit, please blame it on me being a French native
   speaker
   - Sorry if the colours hurt 😅


*Adrien OYONO*
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Accessing parent objects

2018-03-25 Thread Ian Kelly
On Sun, Mar 25, 2018 at 9:01 AM, Jugurtha Hadjar
 wrote:
>
> On 03/25/2018 03:25 PM, Terry Reedy wrote:
>> None.foo will raise AttributeError.
>>
>
> Right.. As I said, I tried to assume as little as possible about OP's code
> and namespace. Didn't want to include C1 in __init__ signature because I
> wasn't sure it was available in the namespace.
>
> It is easy to address, though:
>
> Example A:
>
> class C2(object):
>  def __init__(self, parent=C2):
>  self.parent = parent

This doesn't work as written (try it!)

> Furthermore, having a positional argument will not save us. We can still
> break the code if we do the following:
>
> class C2(object):
> def __init__(self, parent):
> self.parent = parent
> def foo(self):
> self.parent.foo()
>
> c1 = C1()
> c2 = C2(None)
> c2.foo()
>
> Making it positional didn't fix our wickedness.

The difference is that in this case the fault is on the caller for
passing a nonsense value. In the original the fault is on the class
author for providing a useless default and implying that the argument
is not required.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Accessing parent objects

2018-03-25 Thread Terry Reedy

On 3/25/2018 11:01 AM, Jugurtha Hadjar wrote:


On 03/25/2018 03:25 PM, Terry Reedy wrote:

On 3/25/2018 7:42 AM, Jugurtha Hadjar wrote:


class C2(object):
 def __init__(self, parent=None):
 self.parent = parent


Since parent is required, it should not be optional.



You can still call it the way you'd call it if it were a positional 
argument.


You totally missed my point.  Given the definition above, 'parent' can 
be passed either way, but self.parent must be not be None and therefore 
'parent' should not have the unreplaced default value None.  It should 
either have a legal default value or no default value.


--
Terry Jan Reedy


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


Re: Entering a very large number

2018-03-25 Thread Grant Edwards
On 2018-03-25, bartc  wrote:
> On 25/03/2018 02:47, Steven D'Aprano wrote:
>
>> The Original Poster (OP) is concerned about saving, what, a tenth of a
>> microsecond in total? Hardly seems worth the effort, especially if you're
>> going to end up with something even slower.
>
> Using CPython on my machine, doing a string to int conversion that 
> specific number took 200 times as long as doing a normal assignment.
>
> That conversion took 4 microseconds.
>
> Not significant if it's only done once. But it might be executed a 
> million times.

Which adds up to 4 seconds.

Still not worth spending hours (or even a few minutes) to optimize.

-- 
Grant

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


Re: Entering a very large number

2018-03-25 Thread Joe Pfeiffer
bartc  writes:

> On 25/03/2018 15:53, Joe Pfeiffer wrote:
>> ast  writes:
>
>>> C = int(
>>> "28871482380507712126714295971303939919776094592797"
>>> "22700926516024197432303799152733116328983144639225"
>>> "94197780311092934965557841894944174093380561511397"
>>> "4215424169339729054237110027510420801349667317"
>>> "5515285922696291677532547505856101949404200039"
>>> "90443211677661994962953925045269871932907037356403"
>>> "22737012784538991261203092448414947289768854060249"
>>> "76768122077071687938121709811322297802059565867")
>
>> After following the thread for a while...  you will, of course, simply
>> have to do a string to int conversion no matter what approach you take
>> to writing it.
>
> What, even with you write this:
>
>   C = 12
>
> ?

I'm having a hard time parsing that sentence.  If you're pointing out
that when someone writes an int of reasonable length they don't mess
with strings and explicit int conversions, of course you're right.  This
question is specficially about "very large" numbers.

>> The number is a string of digits; it has to be converted
>> to the internal representation.
>
> Which is usually done by a compiler, and it will only do it once not
> each time the line is encountered in a running program. (Although a
> compiler will also do the conversion when the line is never executed!)

If you're using compiled python, yes (though I don't really know how the
bytecode represents long numbers like this, or whether it would optimize
away the explicit int conversion).  Since it's a constant string, it
would be a *really* easy optimization.

>> Even if you write
>>
>> C =
>> 28871482380507712126714295971303939919776094592797227009265160241974323037991527331163289831446392259419778031109293496555784189494417409338056151139742154241693397290542371100275104208013496673175515285922696291677532547505856101949404200039904432116776619949629539250452698719329070373564032273701278453899126120309244841494728976885406024976768122077071687938121709811322297802059565867
>>
>> the conversion happens.
>
> But not at runtime.

If it's not in a loop, only once at runtime in any case.  Does the
interpreter save away constants as it goes, so it would only have to be
done once in any case?
-- 
https://mail.python.org/mailman/listinfo/python-list


issues when buidling python3.* on centos 7

2018-03-25 Thread joseph pareti
I have a VM in the cloud running centos that comes with python 2.7
installed on it. For my purpose, I need python 3.5 (or 6?)

However there is an issue with urlgrabber, and I  believe this is due to
inconsistencies with the 2 python versions, whcih I am not able to resolve.

DETAILS

INSTALL PYTHON 3 from scratch
https://www.digitalocean.com/community/tutorials/how-to-install-python-3-and-set-up-a-local-programming-environment-on-centos-7

change /usr/bin/yum because yum does not support python 3 so force it to
use python 2 in first line, else you get this:
except KeyboardInterrupt, e:

edits in  /usr/libexec/urlgrabber-ext-down to remove syntax errors


sudo yum -y install https://centos7.iuscommunity.org/ius-release.rpm
[joepareti54@xxx ~]$ sudo yum -y install python36u
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * epel: ftp.nluug.nl
 * ius: mirror.amsiohosting.net
Traceback (most recent call last):
  File "/usr/libexec/urlgrabber-ext-down", line 22, in 
from urlgrabber.grabber import \
ModuleNotFoundError: No module named 'urlgrabber'


Exiting on user cancel
[joepareti54@xxx ~]$

therefore

wget
http://mirror.centos.org/centos/7/os/x86_64/Packages/python-urlgrabber-3.10-8.el7.noarch.rpm

sudo yum install python-urlgrabber-3.10-8.el7.noarch.rpm

now rerun sudo yum -y install python36u

basically same as here https://www.centos.org/forums/viewtopic.php?t=52325

the urlgrabber is not found

The following may give a clue because of inconsistent python versions:

[joepareti54@xxx ~]$ python -V
Python 3.5.2 :: Anaconda 4.3.0 (64-bit)

[joepareti54@xxx ~]$ rpm -ql python-urlgrabber | xargs -i dirname '{}' |
sort | uniq | grep site-packages

/usr/lib/python2.7/site-packages
/usr/lib/python2.7/site-packages/urlgrabber
[joepareti54@xxx ~]$

so the install of python-urlgrabber-3.10-8.el7.noarch.rpm landed in the
wrong place as suggested here
https://forums.fedoraforum.org/showthread.php?95680-yum-broken-(-quot-No-module-named-urlgrabber-quot-)
and the inconsistency explains why the grabber module is not found
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Entering a very large number

2018-03-25 Thread bartc

On 25/03/2018 16:47, Grant Edwards wrote:

On 2018-03-25, bartc  wrote:

On 25/03/2018 02:47, Steven D'Aprano wrote:


The Original Poster (OP) is concerned about saving, what, a tenth of a
microsecond in total? Hardly seems worth the effort, especially if you're
going to end up with something even slower.


Using CPython on my machine, doing a string to int conversion that
specific number took 200 times as long as doing a normal assignment.

That conversion took 4 microseconds.

Not significant if it's only done once. But it might be executed a
million times.


Which adds up to 4 seconds.

Still not worth spending hours (or even a few minutes) to optimize.


If this is a program that will only ever be used by one person, and that 
person will only ever run it once, and you know that bit is executed 1M 
time and not 50M, then you might be right.


Remember that 4 seconds might be on top of dozens of other things that 
don't appear to be worth optimising.


The chances are however that a program in development might be run 
hundreds or thousands of times.


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


Re: Accessing parent objects

2018-03-25 Thread Jugurtha Hadjar



On 03/25/2018 04:31 PM, Ian Kelly wrote:

On Sun, Mar 25, 2018 at 9:01 AM, Jugurtha Hadjar
 wrote:

On 03/25/2018 03:25 PM, Terry Reedy wrote:

None.foo will raise AttributeError.


Right.. As I said, I tried to assume as little as possible about OP's code
and namespace. Didn't want to include C1 in __init__ signature because I
wasn't sure it was available in the namespace.

It is easy to address, though:

Example A:

class C2(object):
  def __init__(self, parent=C2):
  self.parent = parent

This doesn't work as written (try it!)


Sorry, I was writing on a my commute and made a mistake. I meant parent=C1.


Furthermore, having a positional argument will not save us. We can still
break the code if we do the following:

class C2(object):
 def __init__(self, parent):
 self.parent = parent
 def foo(self):
 self.parent.foo()

c1 = C1()
c2 = C2(None)
c2.foo()

Making it positional didn't fix our wickedness.

The difference is that in this case the fault is on the caller for
passing a nonsense value. In the original the fault is on the class
author for providing a useless default and implying that the argument
is not required.


The point about the default can be found in my previous answer: If it's 
my code and I know the object I want to use as a default lives in the 
module, I'll provide it as a default parameter, but we're talking about 
C1 and C2 in an abstract way and I chose to make the fewest assumptions 
possibles (maybe too few) OP's code, which may have made the keyword 
argument/positional argument/optional argument/None bubble up. My main 
point in my original reply: I much prefer restricting as little as 
possible and delaying instantiation as much as possible which has helped 
me a lot, especially with testing (for when I don't have access to a 
device represented by the class, or trying to test offline), making the 
library usage easier for myself and others, and avoiding a lot of 
problems down-range (for instance, hot swapping a hardware connection 
after class instantiation is easier when code it's written that way as 
opposed to have it as a required argument). There sure is scar tissue 
and it may not be to everyone's taste, but it has served me well.


Again, I do provide defaults when it's code I write, but I can't guess 
what the original code does so I may have fell into muscle memory.




--
~ Jugurtha Hadjar,

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


Re: Accessing parent objects

2018-03-25 Thread Jugurtha Hadjar


On 03/25/2018 12:07 PM, D'Arcy Cain wrote:

On 03/25/2018 05:10 AM, Jugurtha Hadjar wrote:

     print("I am {self.__class__.__name__} foo".format(self=self))

Unrelated to the original issue but why not one of the following?

print("I am {0.__class__.__name__} foo".format(self))


I prefer keyword arguments, but if I used it that way I'd do:

print("I am {0} foo".format(self.__class__.__name__))

self.__class__.__name__ looks better (+ makes more sense to me) than 
0.__class__.__name__.


print(f"I am {self.__class__.__name__} foo")



f-strings are only available in python 3.6 as far as I know and.

--
~ Jugurtha Hadjar,

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


Re: Ruby parens-free function calls [was Re: Accessing parent objects]

2018-03-25 Thread Rick Johnson
On Sunday, March 25, 2018 at 9:11:35 AM UTC-5, Steven D'Aprano wrote:
> On Sun, 25 Mar 2018 04:49:21 -0700, Rick Johnson wrote:
[...]
> I never said anything about not allowing it. But since
> you've gone on the defence about parens-free function
> calls, how is this for "consistency" in Ruby?
>
> [steve@ando ruby]$ ruby ws-example.rb
> a + b => 7
> a+b   => 7
> a+ b  => 7
> a +b  => 3
>
> Here's the source code:
>
> # --- cut ---
> def a(x=4)
> x+2
> end
>
> b = 1
> print "a + b => ", (a + b), "\n"
> print "a+b   => ", (a+b), "\n"
> print "a+ b  => ", (a+ b), "\n"
> print "a +b  => ", (a +b), "\n"
> # --- cut ---


Short of demonstrating that you have knack for writing
obfuscated code :-), i don't see the point here. One could
easily induce the same level of obfuscation by redefining
numeric operators in an unintuitive manner. But, if your
point is that Ruby's "parens-free function calls" can be
confusing in some highly contrived cases in which the
programmer can't be bothered to write code in a manner that
is intuitive, well then, all we have to do is add the
parens, and poof!, we're back in the land of sanity again.

Here, i took the liberty of un-obfuscating your code by
doing the kind of back-breaking manual labor known only to
the unfortunate inhabitants of Soviet-era gulags, and i did
it by mererly adding the empty parens to each of your method
calls. Here goes:

UH!

> print "a() + b => ", (a + b), "\n"

AG!

> print "a()+b   => ", (a+b), "\n"

OO!

> print "a()+ b  => ", (a+ b), "\n"

EE!

> print "a() +b  => ", (a +b), "\n"

(wipes-sweat-from-brow) Oh boy. That was tough.


> No, its weird because in *both cases* there are no
> arguments given, but in one case there are no arguments
> passed, but in the other case, some unknown number of
> invisible arguments are passed.
>
> Consider a bunch of Ruby function calls:
>
> f()  # calls f with no arguments
> f# calls f with no arguments
> foo()# calls foo with no arguments
> foo  # calls foo with no arguments
> bar()# calls bar with no arguments
> bar  # calls bar with no arguments
> super()  # calls the superclass method with no arguments
> super# MAGIC HAPPENS! calls the superclass method with
>some unknown number of arguments!


The "unknown number of arguments" is equivalent to whatever
is defined by the method. In this form, Ruby's "arg-less-
super" is saving you the trouble of repeating code in a
confined space (aka: method body). Because hey, misspellings
can and do happen ya know. And if the intent of a method is
merely to pass along the arguments _verbatim_ -- which is a
common pattern utilized by OO programmers -- then why bother
with all the superfluous typing and risk the spelling
errors? Besides, Ruby does not abide by the Pythonic concept
of "explicit is better than implicit"; and there is nothing
wrong with that.

Futhermore, since when did you assume that Ruby's super was
a standard func/meth call? Because, it isn't. The only
overlap in consistency between them, is that, as is the case
with Ruby methods, you can call Ruby's super with or without
parenthesis. But the similarities stop there. 

`super` (more generally) is a fundamental feature of most OO
languages which provides a ubiquitous methodology for access
to the superclass object. Now, how exactly that feature is
implemented in each OO language depends greatly on the needs
and opinions of the devs/users of said language. So of
course Ruby's super will not behave _exactly_ like a Ruby
function, nor should it! Neither should it be assumed to
work exactly like Python's super, because now we're talking
about a completely different language with completely
different design philosophy. However, feel free to quote
from any official source which argues (hopefully
compellingly) that Ruby's super somehow fundamentally
violates the nature of what is expected from an OO language.

Finally, you forgot to show the third (explicit argument
passing form) of Ruby's super:

super(ag1, ar2, ..., argN)

> If you want to argue that's a useful feature, okay, I'll
> give you the benefit of the doubt. But useful or not, it's
> still weird and surprising. And deeply, fundamentally
> inconsistent.

I'm not here to protect Ruby. But if Ruby's super is as
"weird and surprising" and "deeply, fundamentally
inconsistent" as you claim it to be, well then, you've
failed to provide sufficient evidence here. 

We are entitled to our own opinions, Steven. But we are not
entitled to our own facts.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Entering a very large number

2018-03-25 Thread ast

Le 25/03/2018 à 03:47, Steven D'Aprano a écrit :

On Sun, 25 Mar 2018 00:05:56 +0100, Peter J. Holzer wrote:






The Original Poster (OP) is concerned about saving, what, a tenth of a
microsecond in total? Hardly seems worth the effort, especially if you're
going to end up with something even slower.




I regret that many answers are malicious, as your.

The question was how to enter a large number without
going through a string, no matter why.
This question is absolutely legitimate, contrary to
some people think.
It seems that it is not feasible unless writting it in
a single line, which is awful.
OK, go on with the string, and Wolfgang solution using
triple quote is good.





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


Re: Accessing parent objects

2018-03-25 Thread Rick Johnson
On Sunday, March 25, 2018 at 10:02:20 AM UTC-5, Jugurtha Hadjar wrote:
[...]
> Furthermore, the only case I'd use a positional argument is
> if I were 100% certain the code will not change, which I'm
> not.

And short of you possessing a crystal ball in good working
order (mine's currently in the shop!), you must always
assume that code will grow over time, and thus, write your
code in a manner that is as easy to extend and maintain as
possible.

> Plus when the API will change (and it will), it will be
> harder to deal with it that if it were a keyword argument.

Huh? Was that a typo? Did you mean "_not_ a kwarg"???

> If you change the order you'd have to change the whole
> codebase where the class/function is instantiated/called,

If the args are positional, then yes.

> whereas if you use a keyword argument, you could just catch
> the old way call, issue a deprecation warning, then route
> the call for the new way call.

Whew! It _was_ a typo. ':-)

> [...]
>
> Suppose I have a class like this:
>
> class Foo(object):
>  def __init__(self, name, height, address):
>  self.name = name
>  self.height = height
>  self.address = address
>
> Suppose I then want to change it to:
>
> class Foo(object):
>  def __init__(self, status, name, address, height):
>  self.status = status
>  self.name = name
>  self.height = height
>  self.address = address
>
>
> This would totally screw up other parts of the code where
> the class is used. I tend to use positional arguments when
> it's *way* unlikely the code will ever change, and even
> then I probably wouldn't.

Positional arguments are not without their practical
advantages though. For instance: you don't have to manually
unpack the arguments into local vars, plus, you can let
Python handle the underflow/overflow of arguments. Of
course, the con is that positional arguments do not scale
nicely; which leads to nasty backwards incompatible issues.

It's a tough call, really. Because as programmers we are
inclined to be naturally lazy (it's a virtue!), and thus,
we'd prefer to offload as much work as we can on the
processor. But if saving a few keystrokes now means hours of
painful search&replace sessions later, hmm, probably best to
choose the path with the best long-term outcome.

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


Re: Entering a very large number

2018-03-25 Thread Peter J. Holzer
On 2018-03-25 19:18:23 +0200, ast wrote:
> Le 25/03/2018 à 03:47, Steven D'Aprano a écrit :
> > The Original Poster (OP) is concerned about saving, what, a tenth of a
> > microsecond in total? Hardly seems worth the effort, especially if you're
> > going to end up with something even slower.
> > 
> > 
> 
> I regret that many answers are malicious, as your.

I just looked up "malicious" in Merriam-Webster, just in case it has
some meaning I wasn't previously aware of.

Nope. It says: 

: having or showing a desire to cause harm to someone
: given to, marked by, or arising from malice

and malice is defined as:

: desire to cause pain, injury, or distress to another
: intent to commit an unlawful act or cause harm without legal
justification or excuse

Can you explain, why you think that Steven (or anybody else in this
thread) wants to cause you harm, pain, injury or distress, or how his
answer constitutes an unlawful act?

> The question was how to enter a large number without
> going through a string, no matter why.

And the answer is: Write it all on one line.

> This question is absolutely legitimate, contrary to
> some people think.

It certainly is. OTOH, the question why you would want to do this is
also legitimate. So is the question why you think that the few
microseconds it takes to parse the string are not acceptable.

And finally:

> It seems that it is not feasible unless writting it in
> a single line, which is awful.
> OK, go on with the string, and Wolfgang solution using
> triple quote is good.

If you think that your solution is not good enough, why do you think
Wolfgang's solution is better? It still converts a string to an int and
it does additional operations on the string. So it is slower and harder
to understand than what you already had. (It also cannot be properly
indented, but you may not care about that.)

hp

-- 
   _  | Peter J. Holzer| we build much bigger, better disasters now
|_|_) || because we have much more sophisticated
| |   | [email protected] | management tools.
__/   | http://www.hjp.at/ | -- Ross Anderson 


signature.asc
Description: PGP signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Accessing parent objects

2018-03-25 Thread Peter J. Holzer
On 2018-03-25 14:49:44 +, Steven D'Aprano wrote:
> The moniker "Python X-thousand" (Python 3000, 4000, 5000...) is usually 
> understood to mean a backwards-compatibility breaking version. Since 
> Python 4 will *not* be such a version, what you are calling 4000 is 
> better called "5000".

If Python 4.0 will "merely be the release that comes after Python
3.9", as Nick Coghlan writes in
https://opensource.com/life/14/9/why-python-4-wont-be-python-3, why will
it be called 4.0 and not 3.10? Just to avoid two-digit minor numbers?

hp

-- 
   _  | Peter J. Holzer| we build much bigger, better disasters now
|_|_) || because we have much more sophisticated
| |   | [email protected] | management tools.
__/   | http://www.hjp.at/ | -- Ross Anderson 


signature.asc
Description: PGP signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Accessing parent objects

2018-03-25 Thread Rick Johnson
On Sunday, March 25, 2018 at 9:52:30 AM UTC-5, Steven D'Aprano wrote:
> On Sun, 25 Mar 2018 04:49:21 -0700, Rick Johnson wrote:
[...]
> But refusing to use super in modern, new-style classes that
> don't have anything to do with tkinter is precisely the
> sort of *foolish* consistency that Emerson was warning
> about.

Oh, obviously! Because in the late 1800's, Python's new
style vs old style classes, and the blinkered state of
Tkinter, was the subject of intense debate in philosophical
circles. Yes-sir-eee!

> Your position is equivalent to noting that tuples don't
> have a sort method, and so "for the sake of consistency"
> refusing to use list.sort() even when you *know* you have a
> list.

That's a BS equivalence and you know it. Tkinter's lack of
new style classes was a design flaw, whereas, tuples are
immutable and a sort method would violate the concept of
immutability.

> Or, and perhaps even more relevant, because *some*
> functions don't support keyword arguments [...] for the
> sake of consistency you must never use keyword arguments
> even though your code would be improved by it

For some definition of "more relevant", i suppose.

> > Thus, a sporadic implementation of super() in my source
> > code would violate the spirit of PEP8.
>
> That's the sort of dubious reading of PEP 8 that Guido was
> warning against in his quote from Emerson.  Just because
> for technical reasons class Foo cannot use super, does not
> mean that you should never use super in any other class for
> the sake of "consistency". Consistency within a single
> class is more important than a foolish consistency across
> all classes.

You cannot even handle basic reading and comprehension, can
you? And i quote _again_ from PEP8:

"""
A style guide is about consistency. Consistency with this
style guide is important. Consistency within a project is
more important. Consistency within one module or function is
the most important.
"""

Using that paragraph as a guide, we can form the following
hierarchal table:

Consistency with every word of PEP8 (important)
Consistency within a project (more important)
Consistency within "scopes" (most important)

My choice to abandon Python's super() in favor of
consistency most directly aligns with the moderate #2
(Consistency within a project). You see Steven, not only is
a single script considered a project; and not *ONLY* is a
package considered a project; but yes, even the aggregate of
all scripts composing an entire library (aka: ricklib!) is a
project. Any questions?

> Especially since by your own admission, you are *giving up
> correctness* in order to buy "consistency":

"sacrificing correctness" only in a purely ideological
sense.

Explicit inheritance (aka: hard-coding the superclass
symbol) works just as well as implicit inheritance (aka:
relying on the "resolution magic" of super). Of course, in
the former case, a slight bit of onerous is placed on the
programmer because he/she must know the exact spelling of
the superclass symbol, whereas, OO's `super` is nothing but
a lazy shortcut which looks up and returns the symbol for
you.

Thus, using super is similar to using a remote control to
open your garage door as opposed to punching in a code.
Either method will open the door just fine. The remote
merely removes the need to remember a code.

It's really not that complicated Steven...

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


Code for Using Keyboard to Play music notes "ABCDEFG"

2018-03-25 Thread Bernard via Python-list

Pyton Friends,
Do you have any code that will play the notes "ABCDEFG" from my computer 
keyboard when a key is pressed ? For example if I press the "a" key the note 
"a" will sound out of my speaker.
Thanks,
BigB
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [OT] multicore/cpu history

2018-03-25 Thread Peter J. Holzer
On 2018-02-19 12:39:51 +0100, Adriaan Renting wrote:
> >>> On 17-2-2018 at 22:02, in message
> ,
> Chris Angelico  wrote: 
> > On Sun, Feb 18, 2018 at 5:05 AM, Steven D'Aprano
> >  wrote:
> >> If you're talking about common desktop computers, I think you're
> >> forgetting how recent multicore machines actually are. I'm having
> >> difficulty finding when multicore machines first hit the market,
> >> but it seems to have been well into the 21st century -- perhaps as
> >> late as 2006 with the AMD Athelon 64 X2:
> > 
> > No, I'm talking about big iron. Has Python been running on multi-CPU
> > supercomputers earlier than that?
> > 
> >> By the way, multiple CPU machines are different from CPUs with
> >> multiple cores:
> >>
> >> http://smallbusiness.chron.com/multiple-cpu-vs-multicore-33195.html
> > 
> > Yeah, it was always "multiple CPUs", not "multiple cores" when I was
> > growing up.

Yes, but the difference is only an implementation detail. Once chips
became large enough that you could fit multiple cores on a single chip
it became cheaper (and faster) to do this than put each core on a
separate chip. Just like modern CPUs may contain a floating point unit,
a memory controller, SATA and ethernet controllers, etc. when previously
those would have been separate chips (or even separate cards).

> > And it was only ever in reference to the expensive
> > hardware that I could never even dream of working with. I was always
> > on the single-CPU home-grade systems.
> > 
> 
> Multicore became a thing with the Pentium 4 hyperthreading around ~2002
> for consumers, and
> multi cpu was a thing much longer, even with "consumer grade"
> hardware:
> 
> I remember running 2 Mendocino 300 MHz Celerons on a Pentium II Xeon
> motherboard to get a
> multi-cpu machine for running multiple virtual machines for testing
> purposes around 1998.

I I bought my first multi-processor computer (a dual pentium-90) in
1995. AFAIK the Pentium was the first Intel processor intended for SMP
(there were multiprocessor systems based on earlier intel processors but
they used custom chipsets and were very much not consumer-grade).

> This was not as Intel intended, but a quite cheap consumer grade
> hardware solution.

My dual pentium wasn't cheap, but the motherboard and the second
processor weren't that expensive. The 21" monitor OTOH ...
and did it have a tape drive? I don't remember, but I think it did.

hp

-- 
   _  | Peter J. Holzer| we build much bigger, better disasters now
|_|_) || because we have much more sophisticated
| |   | [email protected] | management tools.
__/   | http://www.hjp.at/ | -- Ross Anderson 


signature.asc
Description: PGP signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Accessing parent objects

2018-03-25 Thread Chris Angelico
On Mon, Mar 26, 2018 at 7:30 AM, Rick Johnson
 wrote:
>> Especially since by your own admission, you are *giving up
>> correctness* in order to buy "consistency":
>
> "sacrificing correctness" only in a purely ideological
> sense.
>
> Explicit inheritance (aka: hard-coding the superclass
> symbol) works just as well as implicit inheritance (aka:
> relying on the "resolution magic" of super). Of course, in
> the former case, a slight bit of onerous is placed on the
> programmer because he/she must know the exact spelling of
> the superclass symbol, whereas, OO's `super` is nothing but
> a lazy shortcut which looks up and returns the symbol for
> you.

Only, and let me stress that, ONLY, when your classes inherit from
exactly *one* superclass, and you mandate that every class that
inherits from any of your classes ALSO inherits from exactly one
superclass. If *any* class ever inherits from one of your classes and
also something else, hard-coded superclass names become straight-up
wrong.

Have you put code into your classes to prevent anyone from ever
multiply inheriting?

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


Re: Accessing parent objects

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 13:30:14 -0700, Rick Johnson wrote:

[...]
>> Especially since by your own admission, you are *giving up correctness*
>> in order to buy "consistency":
> 
> "sacrificing correctness" only in a purely ideological sense.
> 
> Explicit inheritance (aka: hard-coding the superclass symbol) works just
> as well as implicit inheritance (aka: relying on the "resolution magic"
> of super). 

Except when it doesn't, which is precisely why super was introduced in 
the first place.

(A minor point: if you're going to quote me, quote me correctly: I said 
*giving up* not "sacrificing".)

If your new-style classes don't use super, then they *literally* are 
incorrect, and are either buggy, or have a figurative landmine in your 
class, waiting to go off and introduce a bug if someone is unlucky enough 
to inherit from it under the right circumstances.

Hint: google on "inheritance diamond problem", and maybe you will learn 
something.

You might be lucky enough to use that class for a decade, and never be 
bitten by the flaw. If you never match those right circumstances (or 
perhaps that should be the wrong circumstances), then the flaw will never 
express itself and you may escape introducing an inheritance bug. But 
nevertheless, it will still be there, in your classes, ready to blow up 
in your face.


> Of course, in the former case, a slight bit of onerous is
> placed on the programmer because he/she must know the exact spelling of
> the superclass symbol, whereas, OO's `super` is nothing but a lazy
> shortcut which looks up and returns the symbol for you.

No, *Ruby's super* is nothing but a lazy shortcut. Python's super does a 
lot more.


-- 
Steve

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


Re: String formatting

2018-03-25 Thread D'Arcy Cain
Was "Accessing parent objects."

On 03/25/2018 12:26 PM, Jugurtha Hadjar wrote:
>> print("I am {0.__class__.__name__} foo".format(self))
> 
> I prefer keyword arguments, but if I used it that way I'd do:
> 
> print("I am {0} foo".format(self.__class__.__name__))

These are contrived examples.  In real code I might do something like this:

fmt_class_name = "I am {0.__class__.__name__} foo".format
...
for x class_list:
  print(fmt_class_name(x))

IOW when I define the format string I want it clear what it is supposed
to print.  The actual use of the format could happen in a completely
different place.

> self.__class__.__name__ looks better (+ makes more sense to me) than
> 0.__class__.__name__.
> 
>> print(f"I am {self.__class__.__name__} foo")
> 
> f-strings are only available in python 3.6 as far as I know and.

I'm not even sure if I am a big fan of f-strings but I do like to run
current versions of Python so they are there for me.

-- 
D'Arcy J.M. Cain
Vybe Networks Inc.
http://www.VybeNetworks.com/
IM:[email protected] VoIP: sip:[email protected]
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [OT] multicore/cpu history

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 23:29:07 +0200, Peter J. Holzer wrote:

[...]
>> >> By the way, multiple CPU machines are different from CPUs with
>> >> multiple cores:
>> >>
>> >> http://smallbusiness.chron.com/multiple-cpu-vs-multicore-33195.html
>> > 
>> > Yeah, it was always "multiple CPUs", not "multiple cores" when I was
>> > growing up.
> 
> Yes, but the difference is only an implementation detail.

Not really. With multiple CPUs, you have the option of running two 
distinct OSes in isolation, not merely virtual machines but actual 
distinct machines in the same box. And the CPUs don't necessarily need to 
be the same type, see for example the hybrid Apple Mac/Lisp Machine 
released in the late 1980s or early 90s.

Of course, today, virtualisation is in many practical senses virtually as 
good (pun intended) as actual distinct machines with distinct CPUs, and 
the cost of adding multiple cores is typically cheaper than adding 
multiple CPUs, so there's little point unless you're working with serious 
supercomputer hardware where you need more cores than will fit on a 
single chip.



-- 
Steve

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


Re: Ruby parens-free function calls [was Re: Accessing parent objects]

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 10:33:49 -0700, Rick Johnson wrote:

> On Sunday, March 25, 2018 at 9:11:35 AM UTC-5, Steven D'Aprano wrote:
>> On Sun, 25 Mar 2018 04:49:21 -0700, Rick Johnson wrote:
> [...]
>> I never said anything about not allowing it. But since you've gone on
>> the defence about parens-free function calls, how is this for
>> "consistency" in Ruby?
>>
>> [steve@ando ruby]$ ruby ws-example.rb a + b => 7
>> a+b   => 7
>> a+ b  => 7
>> a +b  => 3
>>
>> Here's the source code:
>>
>> # --- cut ---
>> def a(x=4)
>> x+2
>> end
>>
>> b = 1
>> print "a + b => ", (a + b), "\n"
>> print "a+b   => ", (a+b), "\n"
>> print "a+ b  => ", (a+ b), "\n"
>> print "a +b  => ", (a +b), "\n"
>> # --- cut ---
> 
> 
> Short of demonstrating that you have knack for writing obfuscated code
> :-), i don't see the point here.

[supposed "fix" to the sample script snipped]


You know Rick, every time I start to think that talking to you like an 
adult might result in a productive and intelligent conversation, you pull 
a stunt like this.

Once I recover from laughing at your inability to read a simple eight 
line Ruby script, and then laughing even harder at your inability to tell 
the difference between a string in Ruby and an actual function call, I 
*might* come back and read the rest of your post.



-- 
Steve

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


Re: Accessing parent objects

2018-03-25 Thread Steven D'Aprano
On Sun, 25 Mar 2018 21:50:27 +0200, Peter J. Holzer wrote:

> On 2018-03-25 14:49:44 +, Steven D'Aprano wrote:
>> The moniker "Python X-thousand" (Python 3000, 4000, 5000...) is usually
>> understood to mean a backwards-compatibility breaking version. Since
>> Python 4 will *not* be such a version, what you are calling 4000 is
>> better called "5000".
> 
> If Python 4.0 will "merely be the release that comes after Python 3.9",
> as Nick Coghlan writes in
> https://opensource.com/life/14/9/why-python-4-wont-be-python-3, why will
> it be called 4.0 and not 3.10? Just to avoid two-digit minor numbers?

Yes.



-- 
Steve

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


Re: [OT] multicore/cpu history

2018-03-25 Thread Chris Angelico
On Mon, Mar 26, 2018 at 9:52 AM, Steven D'Aprano
 wrote:
> On Sun, 25 Mar 2018 23:29:07 +0200, Peter J. Holzer wrote:
>
> [...]
>>> >> By the way, multiple CPU machines are different from CPUs with
>>> >> multiple cores:
>>> >>
>>> >> http://smallbusiness.chron.com/multiple-cpu-vs-multicore-33195.html
>>> >
>>> > Yeah, it was always "multiple CPUs", not "multiple cores" when I was
>>> > growing up.
>>
>> Yes, but the difference is only an implementation detail.
>
> Not really. With multiple CPUs, you have the option of running two
> distinct OSes in isolation, not merely virtual machines but actual
> distinct machines in the same box. And the CPUs don't necessarily need to
> be the same type, see for example the hybrid Apple Mac/Lisp Machine
> released in the late 1980s or early 90s.

At what point does it change from being two CPUs to being one CPU and
one auxiliary processing unit? Back in the 80s and early 90s, the
auxiliary was most likely to be a floating-point unit; today, it'd be
a graphics chip. But it could just as easily be a Lisp chip.

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


Re: Entering a very large number

2018-03-25 Thread Richard Damon

On 3/25/18 8:32 AM, bartc wrote:

On 25/03/2018 02:47, Steven D'Aprano wrote:

On Sun, 25 Mar 2018 00:05:56 +0100, Peter J. Holzer wrote:

[...]

yes, good idea


Not if you want to avoid that string to int conversion (as you stated).

That is still there, but in addition you now split the string into a
list and then join the list into a different string.


I'm glad I wasn't the only one who spotted that.

There's something very curious about somebody worried about efficiency
choosing a *less* efficient solution than what they started with. To
quote W.A. Wulf:

"More computing sins are committed in the name of efficiency (without
necessarily achieving it) than for any other single reason — including
blind stupidity."

As Donald Knuth observed:

"We should forget about small efficiencies, say about 97% of the time:
premature optimization is the root of all evil."

The Original Poster (OP) is concerned about saving, what, a tenth of a
microsecond in total? Hardly seems worth the effort, especially if you're
going to end up with something even slower.


Using CPython on my machine, doing a string to int conversion that 
specific number took 200 times as long as doing a normal assignment.


That conversion took 4 microseconds.

Not significant if it's only done once. But it might be executed a 
million times.




The other half of that thought is how does the 4 microseconds to create 
the constant compare to the operations USING that number. My guess is 
that for most things the usage will swamp the initialization, even if 
that is somewhat inefficient.


One option, which in my opinion is more readable, is if you really want 
the efficency is to write the number on a single line, with a place 
guide comment above, something like


# 0112233445
# 12345678901234567890123456789012345678901234567890

foo = 13452356547242573457246245673472457723245634564564

This makes it very clear what the 47th digit of the number is (run the 
guide numbers in the direction that makes sense for you)


Yes, you will have a very long line (several in fact with the guide 
comment), but that 'uglyness' is worth it if the time cost turns out to 
be significant. After all, correctness outweighs elegance (but maybe not 
clarity, but the long line isn't unclear, just a bit ugly), so if the 
time cost make the program violate the specs to be useful, you need a 
bit of ugly to get it to work. (The other option would be to initialize 
into a global variable, which has its own type of ugly)).

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


Re: Entering a very large number

2018-03-25 Thread bartc

On 26/03/2018 00:27, Richard Damon wrote:

On 3/25/18 8:32 AM, bartc wrote:


Using CPython on my machine, doing a string to int conversion that 
specific number took 200 times as long as doing a normal assignment.


That conversion took 4 microseconds.

Not significant if it's only done once. But it might be executed a 
million times.




The other half of that thought is how does the 4 microseconds to create 
the constant compare to the operations USING that number. My guess is 
that for most things the usage will swamp the initialization, even if 
that is somewhat inefficient.


Calling a function that sets up C using 'C = 288714...' on one line, and 
that then calculates D=C+C, takes 0.12 seconds to call 100 times.


To do D=C*C, takes 2.2 seconds (I've subtracted the function call 
overhead of 0.25 seconds; there might not be any function call).


If I instead initialise C using 'C = int("288712...")', then timings 
increase as follows:


0.12  =>   3.7 seconds
2.2   =>   5.9 seconds

So the overhead /can/ be substantial, and /can/ be significant compared 
with doing bignum calculations.


Of course, once initialised, C might be used a hundred times, then the 
overhead is less significant. But it is not small enough to just dismiss.


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


Re: Ruby parens-free function calls [was Re: Accessing parent objects]

2018-03-25 Thread Rick Johnson
On Sunday, March 25, 2018 at 5:57:28 PM UTC-5, Steven D'Aprano wrote:

> [supposed "fix" to the sample script snipped]
>
> You know Rick, every time I start to think that talking to
> you like an adult might result in a productive and
> intelligent conversation, you pull a stunt like this.  Once
> I recover from laughing at your inability to read a simple
> eight line Ruby script, and then laughing even harder at
> your inability to tell the difference between a string in
> Ruby and an actual function call, I *might* come back and
> read the rest of your post.

Q1: Do my modifications throw an error???

If so, then provide this group with the exception message
and you shall be redeemed.

Q2: Did my "fix" fail to meet the highly generalized
qualification of "un-obfuscating the code"???

If not, then explain to this group exactly how i failed.

Steven, your highly competitive nature is apparent
to any and all who frequent this group. And i'm sure i speak
for everyone here when i say that we all appreciate the vast
wealth of knowledge you bring to the table. But this time
you have allowed your emotions to get the better of you, and
now your friendly barbs have become purposeful
misrepresentations.

Listen, if i make a false statement or give bad advice on
this list, then i _want_ someone to call me on it. But for
you to cast accusations without providing any evidence to
support those accusations, is beneath the dignity of this
mailing list. I stand behind my "code fix" and i confidently
claim that not only does it meet the requirements, it also
runs without error. And if you disagree with my claim, then
bring forth your evidence.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Entering a very large number

2018-03-25 Thread Richard Damon

On 3/25/18 9:37 PM, bartc wrote:

On 26/03/2018 00:27, Richard Damon wrote:

On 3/25/18 8:32 AM, bartc wrote:


Using CPython on my machine, doing a string to int conversion that 
specific number took 200 times as long as doing a normal assignment.


That conversion took 4 microseconds.

Not significant if it's only done once. But it might be executed a 
million times.




The other half of that thought is how does the 4 microseconds to 
create the constant compare to the operations USING that number. My 
guess is that for most things the usage will swamp the 
initialization, even if that is somewhat inefficient.


Calling a function that sets up C using 'C = 288714...' on one line, 
and that then calculates D=C+C, takes 0.12 seconds to call 100 times.


To do D=C*C, takes 2.2 seconds (I've subtracted the function call 
overhead of 0.25 seconds; there might not be any function call).


If I instead initialise C using 'C = int("288712...")', then timings 
increase as follows:


0.12  =>   3.7 seconds
2.2   =>   5.9 seconds

So the overhead /can/ be substantial, and /can/ be significant 
compared with doing bignum calculations.


Of course, once initialised, C might be used a hundred times, then the 
overhead is less significant. But it is not small enough to just dismiss.


And my point is that writing a program to just add or multiply once two 
FIXED big long numbers (since they are in the source code, that seems 
fixed), a million times seems  unlikely (and even then the cost isn't 
that bad, since that sounds like a run once program). And of course once 
the answer has been computed, it needs to be output somehow, which 
likely will add to the time significantly. The question would be do you 
have a REAL PRACTICAL case where this overhead actually makes a 
significant difference, or are we just talking a theoretical toy. It is 
a fact that it seems the language has no notation to express such a 
large number as a number in source code on mulitple lines (except as a 
string). I would think it would take something more than a toy program 
to persuade for something notation to do this directly (and there are 
alternatives that have been mentioned that aren't that bad for this sort 
of corner case).


--
Richard Damon

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


Re: Code for Using Keyboard to Play music notes "ABCDEFG"

2018-03-25 Thread Dan Stromberg
I imagine pygame could do this, if you give it:
https://freesound.org/people/pinkyfinger/packs/4409/

On Sun, Mar 25, 2018 at 1:31 PM, Bernard via Python-list
 wrote:
>
> Pyton Friends,
> Do you have any code that will play the notes "ABCDEFG" from my computer 
> keyboard when a key is pressed ? For example if I press the "a" key the note 
> "a" will sound out of my speaker.
> Thanks,
> BigB
> --
> https://mail.python.org/mailman/listinfo/python-list
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Entering a very large number

2018-03-25 Thread Rustom Mody
On Monday, March 26, 2018 at 12:55:43 AM UTC+5:30, Peter J. Holzer wrote:
> On 2018-03-25 19:18:23 +0200, ast wrote:
> > Le 25/03/2018 à 03:47, Steven D'Aprano a écrit :
> > > The Original Poster (OP) is concerned about saving, what, a tenth of a
> > > microsecond in total? Hardly seems worth the effort, especially if you're
> > > going to end up with something even slower.
> > > 
> > > 
> > 
> > I regret that many answers are malicious, as your.

tl;dr:

I plead guilty with my almost first post in this thread containing: «In case 
there is a religious commitment to PEP 8 dicta… »

Apologies!

> 
> I just looked up "malicious" in Merriam-Webster, just in case it has
> some meaning I wasn't previously aware of.
> 
> Nope. It says: 
> 
> : having or showing a desire to cause harm to someone
> : given to, marked by, or arising from malice
> 
> and malice is defined as:
> 
> : desire to cause pain, injury, or distress to another
> : intent to commit an unlawful act or cause harm without legal
> justification or excuse
> 

O come! The OP is apparently not an English speaker; just do
s/malicious/gratuitously unkind/
or just
s/malicious/rude/

My excuse if any is that I was using “religious” in a precise way as
“belief-system” and the over-rigorous commitment to 72 (or whatever) length
lines can be a belief→commitment that produces egregious results

The deeper difficulty is that it is impossible to be human and not have some
non-verifiable beliefs. And yet when these beliefs harden into ossified
religions the results can be unimaginably pernicious

In particular, the complement set: belief-system - classic-religion
can contain the most pernicious examples:  Just compare the number killed in
the name of Islam or Christianity with those killed by communism and divide by
the number of years these 'religions' held sway

Some other examples:

1. Irreligion is a more pernicious belief-system than (classic) religion:
https://youtu.be/6PbYoQw8M48

2. Science as a delusional belief-system:
https://youtu.be/JKHUaNAxsTg

3. New-Atheism as a colonialist project: 
https://aquasanju.wordpress.com/2015/08/08/new-atheists-are-privilege-deniers-sushant-taing/

It is particularly striking that 2 above was banned! Shows how identical are the
subconscious psychological drivers of medieval popes and today's scientists 
(so-called)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Best practice for managing secrets (passwords, private keys) used by Python scripts running as daemons

2018-03-25 Thread Gregory Ewing

Peter J. Holzer wrote:

(Historically, many unixes allowed all users to read the environment
variables of all processes. I don't know if this is still the case for
e.g. Solaris or AIX - or macOS)


A quick test suggests it's still true in MacOSX 10.6:

% ps aeuww
USER   PID  %CPU %MEM  VSZRSS   TT  STAT STARTED  TIME COMMAND
root   254   0.0  0.1  2436216   1668 s000  Ss6:07pm   0:00.02 login -pf 
greg PATH=/usr/bin:/bin:/usr/sbin:/sbin 
TMPDIR=/var/folders/pt/ptWbIBidFOGihAoVFzVWZU+++TI/-Tmp-/ SHELL=/bin/tcsh 
HOME=/Users/greg USER=greg LOGNAME=greg DISPLAY=/tmp/launch-E3mIkg/org.x:0 
SSH_AUTH_SOCK=/tmp/launch-Lq6SPh/Listeners 
Apple_PubSub_Socket_Render=/tmp/launch-k6nWyL/Render COMMAND_MODE=unix2003 
__CF_USER_TEXT_ENCODING=0x1F5:0:0 TERM_PROGRAM=Apple_Terminal 
TERM_PROGRAM_VERSION=273.1 LANG=en_NZ.UTF-8 TERM=xterm-color

...

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


Re: Question regarding objects in __call__() methods

2018-03-25 Thread dieter
Arshpreet Singh  writes:
> ...
> As debugging the code I got at line 10. I am sending a request to particular 
> API and returning a request_object . further deep down it generates the 
> "response_object" as from my requirements that should be JSON object but I am 
> only getting Python-Object in hexa form, is there any way I can get to know 
> how to use internet_object so I can get to know how to use that 
> internet_object with response.

To learn about an unknown object, you could use Python's
"inspection" facilities.

The easiest way is to use the builtin "help" function:
"help(obj)", maybe "help(obj.__class__)". It tells you lots
of useful things about "obj".

Fürther inspection utilities: "dir", "vars" and the "inspect" module.
Read the documentation to find out what they do.

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


Re: Question regarding objects in __call__() methods

2018-03-25 Thread Arshpreet Singh
On Monday, 26 March 2018 11:32:51 UTC+5:30, dieter  wrote:

> Fürther inspection utilities: "dir", "vars" and the "inspect" module.
> Read the documentation to find out what they do.

Thanks, Dieter, That is really helpful!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: A question related to the PYTHONPATH

2018-03-25 Thread dieter
adrien oyono  writes:
> I have recently read the documentation about how imports work on python,
> and I was wondering why, when you execute a python file, the current
> directory is not added by default to the PYTHONPATH ?

Maybe, to avoid surprises?

You can invoke a script from different positions in your file system.
If PYTHONPATH would automatically get ".", the script's behaviour
could depend on the position from where it is called.

Prepending "." to "PYTHONPATH" could have dramatic effects:
assume your script uses module "xxx" and your current working
directory accidentally has a "xxx.py"; then this "xxx.py" would
be used and it may behave much differently from another one.

The problem is not so severe when "." is appended to "PYTHONPATH".
Nevertheless, it likely is not a good idea to have script behaviour
depending by default on the execution location.

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