[Tutor] Tutor Digest, Vol 143, Issue 15

yehudak . katye2007 at gmail.com
Wed Jan 6 09:57:36 EST 2016


Not a question, just ranting.

My 2 commonest coding errors are forgetting the : before a block, and
mismatch between the number of ('s and )'s. The error message is a simple
'Syntax Error', but the line quoted is not the offending line. I would love
a much more explicit 'syntax error'.

Anyone here in good relations with Guido van Rossum?

Yehuda

On Wed, Jan 6, 2016 at 4:46 PM, <tutor-request at python.org> wrote:

> Send Tutor mailing list submissions to
>         tutor at python.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
>         https://mail.python.org/mailman/listinfo/tutor
> or, via email, send a message with subject or body 'help' to
>         tutor-request at python.org
>
> You can reach the person managing the list at
>         tutor-owner at python.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Tutor digest..."
>
>
> Today's Topics:
>
>    1. Thanks Alan. (yehudak .)
>    2. Re: Python 3.5.1 64 bit? (yehudak .)
>    3. Re: Python 3.5.1 64 bit? (Alan Gauld)
>    4. Re: method, type? (Alan Gauld)
>    5. Re: method, type? (Steven D'Aprano)
>    6. Re: method, type? (Steven D'Aprano)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Wed, 6 Jan 2016 09:13:52 +0200
> From: "yehudak ." <katye2007 at gmail.com>
> To: Wally Cow <alan.gauld at btinternet.com>, tutor at python.org
> Subject: [Tutor] Thanks Alan.
> Message-ID:
>         <
> CAE3ie42iGp+1AHK7kidykcHq-dvPWEDffUrOquKkVEk8B0nHEA at mail.gmail.com>
> Content-Type: text/plain; charset=UTF-8
>
> I'll look into it.
> Yehuda
>
>
> ------------------------------
>
> Message: 2
> Date: Wed, 6 Jan 2016 10:14:15 +0200
> From: "yehudak ." <katye2007 at gmail.com>
> To: eryk sun <eryksun at gmail.com>, Wally Cow
>         <alan.gauld at btinternet.com>
> Cc: tutor at python.org
> Subject: Re: [Tutor] Python 3.5.1 64 bit?
> Message-ID:
>         <CAE3ie40uN7GzxXryT4xZTRa9SinnuuDi5TbAehtrzjY5c==
> nDg at mail.gmail.com>
> Content-Type: text/plain; charset=UTF-8
>
> Thanks eryk.
> I've downloaded and installed 3.5.1 64 bit, as Alan suggested.
> So far no problem. I can anytime return to 3.5 if it will be needed.
>
> Yehuda
>
> On Wed, Jan 6, 2016 at 10:01 AM, eryk sun <eryksun at gmail.com> wrote:
>
> > On Wed, Jan 6, 2016 at 1:06 AM, yehudak . <katye2007 at gmail.com> wrote:
> > > What's wrong with upgrading to newer version?
> >
> > It depends on how many systems and virtual environments that you're
> > upgrading. It shouldn't be an issue if it's just a new micro release
> > for your own development machine. If you come across a regression, you
> > can just downgrade to the previous version. That said, there's the old
> > adage that if something isn't broken (for your needs), then you
> > shouldn't 'fix' it.
> >
> > Installing a new minor release (e.g. 3.5 to 3.6) is more work, since
> > you have to reinstall all packages and rebuild extension modules for
> > source packages. But it's worth it to stay current with the evolution
> > of the language. On Windows, make sure to set the PY_PYTHON3
> > environment variable to the version you want as the default "python3".
> >
>
>
> ------------------------------
>
> Message: 3
> Date: Wed, 6 Jan 2016 09:52:00 +0000
> From: Alan Gauld <alan.gauld at btinternet.com>
> To: tutor at python.org
> Subject: Re: [Tutor] Python 3.5.1 64 bit?
> Message-ID: <n6io3v$amg$1 at ger.gmane.org>
> Content-Type: text/plain; charset=utf-8
>
> On 06/01/16 07:06, yehudak . wrote:
> > eryk,
> > Thank you.
> > What's wrong with upgrading to newer version?
>
> There's nothing wrong with it. It's just more work and for
> minor releases often for very little gain. So unless you
> know why you are upgrading you can probably spend your
> time more productively doing other things.
>
> If you are a pro then it might also throw your development
> environment out of sync with your target environment
> which can result in subtle bugs. But I don't think
> that's an issue for you yet.
>
> --
> Alan G
> Author of the Learn to Program web site
> http://www.alan-g.me.uk/
> http://www.amazon.com/author/alan_gauld
> Follow my photo-blog on Flickr at:
> http://www.flickr.com/photos/alangauldphotos
>
>
>
>
> ------------------------------
>
> Message: 4
> Date: Wed, 6 Jan 2016 09:59:49 +0000
> From: Alan Gauld <alan.gauld at btinternet.com>
> To: tutor at python.org
> Subject: Re: [Tutor] method, type?
> Message-ID: <n6ioik$hq7$1 at ger.gmane.org>
> Content-Type: text/plain; charset=utf-8
>
> On 06/01/16 04:58, Alex Kleider wrote:
>
> > class JournalLineItem(object):
> >      def __init__(self, account, debit_or_credit, amount):
> >          self.account = account
> >          self.debit_or_credit = debit_or_credit
> >          self.amount = float(amount)
> >
> ...
> >      def get_line_item(text):
> >          return JournalLineItem(*text.split())
>
> > What kind of a method/function is get_line_item?
>
> As it stands its not.
> As its intended to be, its a named constructor.
> But Python doesn't support named constructors so instead it
> could be a class method - that is a method of the class
> rather than of a particular instance.
>
> But it should probably be a factory function. That is,
> defined at the module level and not part of the class
> at all. Not everything in OOP needs to be in a class.
>
>
> --
> Alan G
> Author of the Learn to Program web site
> http://www.alan-g.me.uk/
> http://www.amazon.com/author/alan_gauld
> Follow my photo-blog on Flickr at:
> http://www.flickr.com/photos/alangauldphotos
>
>
>
>
> ------------------------------
>
> Message: 5
> Date: Wed, 6 Jan 2016 21:49:29 +1100
> From: Steven D'Aprano <steve at pearwood.info>
> To: tutor at python.org
> Subject: Re: [Tutor] method, type?
> Message-ID: <20160106104929.GM23700 at ando.pearwood.info>
> Content-Type: text/plain; charset=us-ascii
>
> On Tue, Jan 05, 2016 at 08:58:42PM -0800, Alex Kleider wrote:
>
> > class JournalLineItem(object):
> >     def __init__(self, account, debit_or_credit, amount):
> >         self.account = account
> >         self.debit_or_credit = debit_or_credit
> >         self.amount = float(amount)
> >     def show(self):
> >         return ("ACNT: {}  ${:0.2f} {}".
> >             format(self.account, self.amount, self.debit_or_credit))
> >     def get_line_item(text):
> >         return JournalLineItem(*text.split())
> >
> > def test():
> >     print(
> >     JournalLineItem.get_line_item("2435 Dr 25.33").show())
>
>
> > What kind of a method/function is get_line_item?
>
> In Python 3, it's a regular function. In Python 2, it's a broken method
> that won't work.
>
> Some background information: methods and functions are different
> kinds of things, but methods are constructed from functions as
> needed. So when you define a method inside a class:
>
> class Spam:
>     def method(self, arg): ...
>
> you're actually defining an ordinary function object. All the magic
> takes place when you go to use it. The rules changed slightly in Python
> 3, so I'll start with Python 2.
>
> Normal use is to create an instance, then call the method:
>
> instance = Spam()
> instance.method(x)
>
> At this point, calling instance.method extracts the function object out
> of the class, converts it into a "bound method", and calls that method.
>
> ("Bound" in this context only means that the method knows what instance
> it will get as self.)
>
> If you extract the method from the class instead, you get an "unbound
> method" which means it doesn't have an instance applied to it, so you
> have to provide one yourself:
>
> Spam.method(instance, x)
>
>
> We can see that the class actually stores a regular function object,
> which is then automatically converted into methods as required:
>
> py> Spam.__dict__['method']
> <function method at 0xb7c0f79c>
> py> Spam().method
> <bound method Spam.method of <__main__.Spam instance at 0xb7c0e22c>>
> py> Spam.method
> <unbound method Spam.method>
>
> The magic that makes this work is called the Descriptor protocol, and it
> is responsible for all sorts of goodies, like properties, staticmethods,
> classmethods, and more.
>
> So, that was the situation in Python 2. When Python 3 came about, people
> realised that there actually isn't anything special about unbound
> methods. They're just functions, and so in Python 3 extracting a method
> off the class just returns the regular function, with no changes made:
>
> py> Spam.__dict__['method']
> <function Spam.method at 0xb7ade14c>
> py> Spam().method
> <bound method Spam.method of <__main__.Spam object at 0xb7b5a86c>>
> py> Spam.method
> <function Spam.method at 0xb7ade14c>
>
>
> Your JournalLineItem class takes advantage of that fact. When you go to
> use the get_line_item "method", you extract it from the class:
>
>     JournalLineItem.get_line_item
>
> which returns an ordinary function, as if it were defined outside of a
> class. You then provide an argument:
>
>     JournalLineItem.get_line_item("2435 Dr 25.33")
>
> which gets assigned to the parameter "text" and various things happen.
>
> Although this is legal code, it should be avoided because:
>
> (1) It is confusing and weird.
>
> (2) If you try calling the method from an instance, bad things happen:
>
> py> x = JournalLineItem("account", True, 100)
> py> x.get_line_item("2435 Dr 25.33")
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: get_line_item() takes 1 positional argument but 2 were given
>
>
> This is how get_line_item should be written:
>
>     @classmethod
>     def get_line_item(cls, text):
>         return cls(*text.split())
>
> which also has the advantage that if you subclass JournalLineItem, the
> method will continue to work correctly.
>
>
> > From what I've read (and not fully understood)
> > static methods and class methods must have
> > @staticmethod and @classmethod on the line above them.
>
> In simple terms, correct.
>
> To be technical, not quite, there are other, less convenient but
> sometimes useful, ways to create static and classmethods, but you don't
> need to worry about those if you don't want. (I'll explain if you ask.)
>
>
> > get_line_item works as I wanted but it's clearly not the
> > usual type of method and I don't know how to categorize it.
> > It's an instance creator- is there a better term?
> > Is this 'Pythonic' code?
>
> The usual term for this is "alternate constructor", or just
> "constructor". It constructs an instance of the class, you see, but it
> is not the standard one, __init__.
>
> (To be precise, __init__ is the initiator, __new__ is the actual
> constructor, but most of the time you don't write __new__, and it calls
> __init__ by default.)
>
> Is it Pythonic? As written, hell no! It's a mess! (No offense intended.)
> It confused me, for a while, I really thought it wouldn't work at all
> and was somewhat surprised to see that it did actually work. (Once I saw
> that it worked, in hindsight it was obvious why it worked.)
>
> But the principle is sound. For example, dicts have an alternate
> constructor method:
>
>     dict.fromkeys
>
> which creates a new dict from a collection of keys.
>
> So I recommend you re-write the method to the version I suggested, and
> then you can happily use it secure in the knowledge that not only does
> it work, but it works in a Pythonic way.
>
>
>
>
> --
> Steve
>
>
> ------------------------------
>
> Message: 6
> Date: Thu, 7 Jan 2016 01:46:08 +1100
> From: Steven D'Aprano <steve at pearwood.info>
> To: tutor at python.org
> Subject: Re: [Tutor] method, type?
> Message-ID: <20160106144608.GA10854 at ando.pearwood.info>
> Content-Type: text/plain; charset=us-ascii
>
> On Wed, Jan 06, 2016 at 09:59:49AM +0000, Alan Gauld wrote:
> > On 06/01/16 04:58, Alex Kleider wrote:
> >
> > > class JournalLineItem(object):
> > >      def __init__(self, account, debit_or_credit, amount):
> > >          self.account = account
> > >          self.debit_or_credit = debit_or_credit
> > >          self.amount = float(amount)
> > >
> > ...
> > >      def get_line_item(text):
> > >          return JournalLineItem(*text.split())
> >
> > > What kind of a method/function is get_line_item?
> >
> > As it stands its not.
>
> Actually, it is a function, because `def` ALWAYS creates a function.
>
>
> > As its intended to be, its a named constructor.
> > But Python doesn't support named constructors so instead it
> > could be a class method - that is a method of the class
> > rather than of a particular instance.
>
> I don't understand what you mean by "Python doesn't support named
> constructors". It seems to me that this is the *only* sort of
> constructor that Python supports.
>
> As I understand it, "named constructor" comes from the C++ world, where
> functions are matched not just by name, but by parameters as well.
>
> https://isocpp.org/wiki/faq/ctors#named-ctor-idiom
>
>
> Constructors are named the same as the class by default. So, using
> Python syntax for simplicity, this is how you would define two
> constructors for a class called Spam, one that takes a single argument,
> and the other which takes two arguments:
>
>
> class Spam:
>     def Spam(x):
>        # create a new Spam instance from one argument, x
>
>     def Spam(x, y):
>        # create a new Spam instance from two arguments, x and y
>
>
> When you go to create an instance, you have a choice of saying:
>
> x = Spam("arg")  # calls the one argument constructor
> y = Spam(23, 99)  # calls the two argument constructor
>
> and the C++ compiler will automatically choose the right constructor
> method.
>
> But what if you need two constructors with the same number and type of
> arguments? For instance, you might have a Coordinate object, which takes
> two integers representing the position relative to the entire screen, or
> two integers representing the position relative to the current window.
> The C++ compiler cannot distinguish those two cases, and would give an
> error.
>
> The solution is to use constructors with different names, which C++
> calls "named constructors".
>
> But note that Python DOES NOT support the standard name-of-class kind of
> constructor that C++ uses. In Python, we would write __new__ or
> __init__, not Spam, but that's just a cosmetic difference. The big
> difference is that we cannot write two methods with the same name and
> have Python keep them both. The second method would overwrite the first.
> So the only way to have two different constructors is to give them
> different names.
>
> Hence all constructors in Python are "named constructors".
>
>
> > But it should probably be a factory function. That is,
> > defined at the module level and not part of the class
> > at all. Not everything in OOP needs to be in a class.
>
> It would be reasonable to make this a factory function declared in the
> global module level. But I think making it a classmethod is better. That
> keeps it encapsulated with the class, and ensures that if you subclass
> the class, you automatically get a valid constructor as well.
>
>
>
> --
> Steve
>
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> https://mail.python.org/mailman/listinfo/tutor
>
>
> ------------------------------
>
> End of Tutor Digest, Vol 143, Issue 15
> **************************************
>


More information about the Tutor mailing list