Re: Style Q: Instance variables defined outside of __init__

2018-03-21 Thread Rustom Mody
On Wednesday, March 21, 2018 at 5:37:48 AM UTC+5:30, Paul Rubin wrote:
> Ben Finney  writes:
> > Any program which needs to interact with systems outside itself – which
> > is to say, any program which performs useful work, ultimately – must
> > have side effects. So it's absurd to advocate removing *all* side
> > effects.
> 
> The way it (conceptually) works in Haskell is you write a purely
> functional program that returns a pure value of type "I/O action".  

Saw this coincidentally adjacent to this thread

https://youtu.be/ROor6_NGIWU

Its a view 'from the other side': a big name in functional programming
(not haskell) musing on how the world of IO, more generally world interaction,
could be cleaned up
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Ben Finney
Steven D'Aprano  writes:

> What they came up with is that its really hard to do useful work for 
> large applications with 100% pure functional programming styles. As you 
> add functional techniques to your code, you find your code quality 
> increasing. Things like pure functions with no hidden state and no side 
> effects can have a massive positive effect on code quality -- up to a 
> point.
>
> As you approach closer and closer to 100% pure functional code, you get 
> fewer improvements and your code gets harder to write and maintain.

Right. I hope no-one advocates a *purely* functional approach to any
program that needs to do work on anything external.

Functional programming is a paradigm that is an essential tool to
*minimise* the side-effects of code, with a corresponding increase in
the testability and therefore the confidence one can place in that code.

Any program which needs to interact with systems outside itself – which
is to say, any program which performs useful work, ultimately – must
have side effects. So it's absurd to advocate removing *all* side
effects.

So, those who sneer that Python isn't purely functional are, in my view,
paying Python a compliment: that it doesn't get in the way of doing
useful work on things people care about getting done. Python supports a
highly functional style, while not going IMO too far down the road of
purity at the expense of usefulness.

-- 
 \“The reason we come up with new versions is not to fix bugs. |
  `\ It's absolutely not.” —Bill Gates, 1995-10-23 |
_o__)  |
Ben Finney

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread codewizard
On Tuesday, March 20, 2018 at 1:10:19 PM UTC-4, Irv Kalb wrote:
> I am aware of all the issues involved.  My example code was an attempt to 
> demonstrate the clearest, simplest case possible.  My question is not about 
> this small case.  In classes designed for full games, I often have a "reset" 
> method that resets many instance variables (and potentially other display 
> fields and graphics) for a new round of playing a game.  Grouping this into a 
> method called something like "reset" makes logical sense to me.  You tell the 
> game object to reset itself, and it does whatever it needs to do to reset for 
> a new round.  My __init__ method calls reset to initialize the first round of 
> the game.  This ensures that every play of the game goes through the same 
> initialization.

Calling reset() from __init__() and duplicating resetting logic during 
initialization aren't the only choices.

My personal preference in such situations is to put all initialization code in 
__init__. Then write a separate factory function / method to create the new 
object for the next round. Optionally, this factory can be parametrized by the 
previous round object.

Regards,
Igor.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [OT] Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Grant Edwards
On 2018-03-20, Tom Evans via Python-list  wrote:
> On Tue, Mar 20, 2018 at 5:25 PM, Grant Edwards
> wrote:
>> On 2018-03-20, Neil Cerutti  wrote:
>>
>>> My automotive course will probaly divide cars into Automatic
>>> Transmission, and Front Wheel Drive.
>>
>> I get your point: the two characteristics are, in theory, orthogonal.
>> But, in the US, the two appear to be correlated.  ISTM that cars with
>> manual transmissions are much more likely to be RWD than are
>> automatics.
>
> I find that slightly strange, I guess in the US, manual transmission
> correlates to the non default option(?), along with RWD.

In the US, manual transmissions are only offered on "sport"
models/packges which tend to be sold to people who know/care more
about cars that the average driver.  Those models are also much more
likely to be RWD because those people are much more likely to prefer
the handling of RWD over that of FWD.

> In Europe, RWD and automatic transmission are more expensive options
> than FWD and manual transmissions, and most cars are FWD and manual.

In the US, cars with manual transmission tend to be high priced
because they are higher-performance, sports/enthusiast cars.  They're
either traditional US V8 muscle cars like Ford Mustangs and Dodge
Callengers, or they're models trying to compete with BMW 3 and 5
series.

They may be cheaper than similar performing cars with automatics
(which are now often high-tech dual-clutch 8-speed mechanical
wonders), but more expensive than the _average_ automatic transmission
car.

-- 
Grant Edwards   grant.b.edwardsYow! I'm having a BIG BANG
  at   THEORY!!
  gmail.com

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


[OT] Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Tom Evans via Python-list
On Tue, Mar 20, 2018 at 5:25 PM, Grant Edwards
 wrote:
> On 2018-03-20, Neil Cerutti  wrote:
>
>> My automotive course will probaly divide cars into Automatic
>> Transmission, and Front Wheel Drive.
>
> I get your point: the two characteristics are, in theory, orthogonal.
> But, in the US, the two appear to be correlated.  ISTM that cars with
> manual transmissions are much more likely to be RWD than are
> automatics.

I find that slightly strange, I guess in the US, manual transmission
correlates to the non default option(?), along with RWD.

In Europe, RWD and automatic transmission are more expensive options
than FWD and manual transmissions, and most cars are FWD and manual.

At least most cars I can afford..

Cheers

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Chris Angelico
On Wed, Mar 21, 2018 at 4:18 AM, Neil Cerutti  wrote:
> The Introduction to Computer Science class I'm taking divided
> program design into two categories: Top Down Design, and Object
> Oriented Design. It's good, because it reminded me of the wisdom
> of dividing memory into Random Access and Read Only.
>
> My automotive course will probaly divide cars into Automatic
> Transmission, and Front Wheel Drive.

Game reviews on Steam can be rated as Helpful, Unhelpful, or Funny,
thus giving a ternary division of similar quality.

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Grant Edwards
On 2018-03-20, Neil Cerutti  wrote:

> My automotive course will probaly divide cars into Automatic
> Transmission, and Front Wheel Drive.

I get your point: the two characteristics are, in theory, orthogonal.
But, in the US, the two appear to be correlated.  ISTM that cars with
manual transmissions are much more likely to be RWD than are
automatics.

-- 
Grant Edwards   grant.b.edwardsYow! Inside, I'm already
  at   SOBBING!
  gmail.com

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Neil Cerutti
On 2018-03-20, Rick Johnson  wrote:
> On Tuesday, March 20, 2018 at 6:14:34 AM UTC-5, Alister wrote:
>> On Tue, 20 Mar 2018 08:52:29 +, Steven D'Aprano wrote:
>> > On Tue, 20 Mar 2018 02:43:13 -0400, Terry Reedy wrote:
>> > 
>> > > I think a claim that in all programs all attributes
>> > > should be set *in* __init__, as opposed to *during*
>> > > initialization, is wrong.  All attribute setting is side-
>> > > effect from a functional view (and usually 'bad' to a
>> > > functionalist).  There is no reason to not delegate some
>> > > of it to sub-init functions when it makes sense to do do.
>> > > There is good reason to do so when it makes the code
>> > > easier to understand *and test*.
>> > 
>> > That is really well said Terry, thank you for articulating
>> > what I was thinking but couldn't find the words for.
>> 
>> but why would a functional programmer be programming an OOP
>> class?
>
> The question does indeed beg, but we're not allowed to
> question mandates form "on high", we are simply required to
> follow them.
>
> IOWs, "Do as they _say_, not as logic dictates"

The Introduction to Computer Science class I'm taking divided
program design into two categories: Top Down Design, and Object
Oriented Design. It's good, because it reminded me of the wisdom
of dividing memory into Random Access and Read Only.

My automotive course will probaly divide cars into Automatic
Transmission, and Front Wheel Drive.

-- 
Neil Cerutti

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Irv Kalb

> On Mar 19, 2018, at 10:27 AM, Ned Batchelder  wrote:
> 
> On 3/19/18 1:04 PM, Irv Kalb wrote:
>> I am building some classes for use in future curriculum.  I am using PyCharm 
>> for my development.  On the right hand edge of the PyCharm editor window, 
>> you get some little bars indicating warnings or errors in your code.  I like 
>> this feature and try to clean up as many of those as I can.  However, there 
>> is one warning that I am seeing often, and I'm not sure about how to handle 
>> it.  The warning I see is:
>> 
>> "Instance attribute  defined outside of __init__ ..."
>> 
>> 
> 
> I understand this tension: it's nice to assign only meaningful values, and to 
> do it in as few places as possible.  But it's also nice to have all of your 
> attributes in one place.  This is a by-product of Python having no 
> declarations, only definitions (assignments).  So to mention the attributes 
> initially, you have to choose a value for them.  If I were to add faceUp to 
> __init__, I would assign False to it.
>> 

Thanks to everyone who responded to my question - good discussion.  Special 
thanks to Ned who accurately described the "tension" that I am trying to 
resolve.

I am aware of all the issues involved.  My example code was an attempt to 
demonstrate the clearest, simplest case possible.  My question is not about 
this small case.  In classes designed for full games, I often have a "reset" 
method that resets many instance variables (and potentially other display 
fields and graphics) for a new round of playing a game.  Grouping this into a 
method called something like "reset" makes logical sense to me.  You tell the 
game object to reset itself, and it does whatever it needs to do to reset for a 
new round.  My __init__ method calls reset to initialize the first round of the 
game.  This ensures that every play of the game goes through the same 
initialization.

With the approach suggested (initializing instance variables in my __init__ and 
in method like reset), I would wind up duplicating all such code.  I know 
myself, and I am worried that this has the potential for introducing an error 
in my coding (specifically, add an initialization of an instance variable in my 
__init__ but then forget to add the same line in my "reset" method).  So the 
tension that I am feeling is in the trade off of the "Don't Repeat Yourself" 
(DRY) rule vs the nicety of defining all instance variables in the __init__ 
method, and with that a resolution to the lint warnings.  

After further thought (and considering by the discussion here), I think that 
the DRY rule outweighs the other.  I will keep my separate initialization 
methods, and call them at the end of my __init__ methods.

Again, the real reason I'm asking for the "best practices" (even though I hate 
that term), is because I want to explain this concept to students who will be 
learning the basics of OOP.  

Thanks,

Irv

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Chris Angelico
On Wed, Mar 21, 2018 at 2:15 AM, Steven D'Aprano
 wrote:
> On Tue, 20 Mar 2018 11:14:13 +, Alister via Python-list wrote:
>
>> but why would a functional programmer be programming an OOP class?
>
> I read a really good blog post a while back, which I sadly can no longer
> find (I had it bookmarked until Firefox ate my bookmarks) that discussed
> exactly that question.
>
> What they came up with is that its really hard to do useful work for
> large applications with 100% pure functional programming styles. As you
> add functional techniques to your code, you find your code quality
> increasing. Things like pure functions with no hidden state and no side
> effects can have a massive positive effect on code quality -- up to a
> point.
>
> As you approach closer and closer to 100% pure functional code, you get
> fewer improvements and your code gets harder to write and maintain.
>
> He maintains that the sweet spot is about 80% functional, and 20% OOP.

Yep, I remember that article. Sadly, I can't find it back now either;
maybe someone can craft a regular expression to find it?
https://xkcd.com/208/

This week I dived into the source code for an application that's built
out of 20 Python files in four package directories plus a top-level
"app.py" as its entry point. You'd think that that means I can write
my own Python script that imports from those packages and calls on the
same code, right? Sadly, no; because this app is 100% OOP and 0%
functional. (Not to be confused with a *non-functioning* app; it
functions perfectly well. It just doesn't follow *functional
programming* idioms.) Deep inside the imported modules, a class's
__init__ will check command-line arguments to control its behaviour,
and in the event of a problem (eg JSON data lacking vital
information), will print a failure message and exit the program. Were
this class written in a pure functional style, it would use the
construction parameters, and raise an exception if something's wrong.
It's entirely possible for a class to follow functional programming
style, at least partly.

(In theory, it should be possible to use a class in a 100% functional
style. A class is just a callable function that then happens to return
a thing of a type that has the same name as the thing you called, so
there's no reason the two styles can't completely overlap.)

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Steven D'Aprano
On Tue, 20 Mar 2018 11:14:13 +, Alister via Python-list wrote:

> but why would a functional programmer be programming an OOP class?

I read a really good blog post a while back, which I sadly can no longer 
find (I had it bookmarked until Firefox ate my bookmarks) that discussed 
exactly that question.

What they came up with is that its really hard to do useful work for 
large applications with 100% pure functional programming styles. As you 
add functional techniques to your code, you find your code quality 
increasing. Things like pure functions with no hidden state and no side 
effects can have a massive positive effect on code quality -- up to a 
point.

As you approach closer and closer to 100% pure functional code, you get 
fewer improvements and your code gets harder to write and maintain.

(Think about things like dealing with user preferences, and having to 
pass them around from function to function. Think about functions that 
don't need a parameter themselves, but need to call a function that does. 
Think about data processing without any mutable data structures. 
Sometimes a modicum of state is exactly what we need.)

He maintains that the sweet spot is about 80% functional, and 20% OOP. 
That seems to be about right to me: write classes with just the bare 
minimum state you need, and have your methods work using a nearly-pure 
functional style: they should take arguments, they should return results, 
they should rarely operate by side-effects, etc.

Most of Python's design is like that. Apart from a few mutable data 
structures, Python's built-ins tend to be immutable. We don't do things 
like:

finder = SubstringFinder(start=1, end=55)
finder.set_string(string_to_search)
finder.set_target(substring)
position = finder.find()

rather we use the semi-functional style:

position = string_to_search.find(substring, start=1, end=55)


Don't be fooled by the dot method call syntax: that's exactly equivalent 
to the purely functional style

find(string_to_search, substring, start=1, end=55)



-- 
Steve

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Rick Johnson
On Tuesday, March 20, 2018 at 1:43:39 AM UTC-5, Terry Reedy wrote:
[...]
> > class Card():
> >
> >  BACK_OF_CARD_IMAGE = pygame.image.load('images/backOfCard.png')
> >
> >  def __init__(self, window, name, suit, value):
> >  self.window = window
> >  self.suit = suit
> >  self.cardName = name + ' of ' + suit
> >  self.value = value
> >  fileName = 'images/' + self.cardName + '.png'
> >  self.image = pygame.image.load(fileName)
> >  self.backOfCardImage = Card.BACK_OF_CARD_IMAGE
> >
> >  self.conceal()
> >
> >  def conceal(self):
> >  self.faceUp = False
> >
> >  def reveal(self):
> >  self.faceUp = True
>
> If the single line is all these functions do, I *might*
> suggest getting rid of them.  But this is really a separate
> issue.

While i normally agree with your advice Terry, in this case,
i must protest as i am a firm believer that callers should
_never_ be fiddling with the internals of an object unless
doing so is the only available option -- and such cases of
last resort indicate a code-smell.

Whether the practice is considered Pythonic or not (i don't
care), i would strongly suggest to the OP and anyone within
ear shot, that clear interfaces must be _strictly_ utilized.

Sure, in this case a named function may be overkill,
however, even in the superfluous cases, not providing an
interface encourage callers to engage in sloppy behavior and
reinforces sloppy behavior in authors. And both parties will
be doomed to maintenance nightmares when `reveal` and/or
`conceal` grow more functional behavior.

Laziness is not always a bad thing -- i mean, let's face it
folks, python is designed to be a lazy language -- but
experience has proven that when an author refuses to provide
clear interfaces to his/her objects, the author and the
caller will both pay a heavy price in the future.

IOWs, laziness should never be allowed to wax into an
orthodoxy.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Rick Johnson
On Tuesday, March 20, 2018 at 6:14:34 AM UTC-5, Alister wrote:
> On Tue, 20 Mar 2018 08:52:29 +, Steven D'Aprano wrote:
> > On Tue, 20 Mar 2018 02:43:13 -0400, Terry Reedy wrote:
> > 
> > > I think a claim that in all programs all attributes
> > > should be set *in* __init__, as opposed to *during*
> > > initialization, is wrong.  All attribute setting is side-
> > > effect from a functional view (and usually 'bad' to a
> > > functionalist).  There is no reason to not delegate some
> > > of it to sub-init functions when it makes sense to do do.
> > > There is good reason to do so when it makes the code
> > > easier to understand *and test*.
> > 
> > That is really well said Terry, thank you for articulating
> > what I was thinking but couldn't find the words for.
> 
> but why would a functional programmer be programming an OOP
> class?

The question does indeed beg, but we're not allowed to
question mandates form "on high", we are simply required to
follow them.

IOWs, "Do as they _say_, not as logic dictates"
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Grant Edwards
On 2018-03-20, Alister via Python-list  wrote:

> but why would a functional programmer be programming an OOP class?

Part of a 12-step recovery plan? 

;)

-- 
Grant Edwards   grant.b.edwardsYow! Hello.  I know
  at   the divorce rate among
  gmail.comunmarried Catholic Alaskan
   females!!

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Alister via Python-list
On Tue, 20 Mar 2018 08:52:29 +, Steven D'Aprano wrote:

> On Tue, 20 Mar 2018 02:43:13 -0400, Terry Reedy wrote:
> 
>> I think a claim that in all programs all attributes should be set *in*
>> __init__, as opposed to *during* initialization, is wrong.  All
>> attribute setting is side-effect from a functional view (and usually
>> 'bad' to a functionalist).  There is no reason to not delegate some of
>> it to sub-init functions when it makes sense to do do.  There is good
>> reason to do so when it makes the code easier to understand *and test*.
> 
> That is really well said Terry, thank you for articulating what I was
> thinking but couldn't find the words for.

but why would a functional programmer be programming an OOP class?




-- 
No one becomes depraved in a moment.
-- Decimus Junius Juvenalis
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Style Q: Instance variables defined outside of __init__

2018-03-20 Thread Steven D'Aprano
On Tue, 20 Mar 2018 02:43:13 -0400, Terry Reedy wrote:

> I think a claim that in all programs all attributes should be set *in*
> __init__, as opposed to *during* initialization, is wrong.  All
> attribute setting is side-effect from a functional view (and usually
> 'bad' to a functionalist).  There is no reason to not delegate some of
> it to sub-init functions when it makes sense to do do.  There is good
> reason to do so when it makes the code easier to understand *and test*.

That is really well said Terry, thank you for articulating what I was 
thinking but couldn't find the words for.



-- 
Steve

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-19 Thread Terry Reedy

On 3/19/2018 1:04 PM, Irv Kalb wrote:

However, there is one warning that I am seeing often, an > I'm not sure about 
how to handle it.  The warning I see is:

"Instance attribute  defined outside of __init__ ..."


Style checkers are notorious for sometimes giving bad advice and being 
overly opinionated.


I think a claim that in all programs all attributes should be set *in* 
__init__, as opposed to *during* initialization, is wrong.  All 
attribute setting is side-effect from a functional view (and usually 
'bad' to a functionalist).  There is no reason to not delegate some of 
it to sub-init functions when it makes sense to do do.  There is good 
reason to do so when it makes the code easier to understand *and test*.


Example: the IDLE's options setting dialog.  Until last summer, it was 
one class* with at perhaps a thousand lines of initialization code (with 
no automated test).  To me, the dictate that they should have all been 
in the __init__ function is absurd.  Fortunately, there were about 9 
subsidiary functions.


* We split off a class for each tab, but keep the separate functions to 
create the tab page widgets and load them with current values.



The following is a simple example.  I am creating a card class that I am using 
to build card games with PyGame.
class Card():

 BACK_OF_CARD_IMAGE = pygame.image.load('images/backOfCard.png')

 def __init__(self, window, name, suit, value):
 self.window = window
 self.suit = suit
 self.cardName = name + ' of ' + suit
 self.value = value
 fileName = 'images/' + self.cardName + '.png'
 self.image = pygame.image.load(fileName)
 self.backOfCardImage = Card.BACK_OF_CARD_IMAGE

 self.conceal()

 def conceal(self):
 self.faceUp = False

 def reveal(self):
 self.faceUp = True


If the single line is all these functions do, I *might* suggest getting 
rid of them.  But this is really a separate issue.


--
Terry Jan Reedy

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-19 Thread Steven D'Aprano
On Mon, 19 Mar 2018 10:04:53 -0700, Irv Kalb wrote:

> Some people say
> that this type of thing is fine and these warnings should just be
> ignored.  While others say that all instance variables should be defined
> in the __init__ method.

Whenever anyone says "you should do this", the question to ask is, "what 
bad thing will happen if I don't?"

You are getting a warning that self.faceUp is not defined in __init__. 
That means that there must be something bad that will happen if you don't 
define faceUp in __init__. Any idea what?

If there is no such bad thing that will happen, then PyCharm is crying 
wolf: it is wasting your time with a warning for a non-problem.


> I like that idea (and have done so in other
> languages), but if I define this variable there, what value should I
> give it?  Do I redundantly set it to the proper starting value (in case
> False), 

Why is it redundant? Since you're going to call conceal() anyway, why not 
just set the value and not bother with conceal? Especially since conceal 
appears to do nothing but set the flag.

Maybe it is *conceal* which is redundant and needs to be removed. On the 
other hand, 

instance.conceal()
instance.reveal()

is much more descriptive than "faceUp = True".


> or do as others have suggested, set it to None (which seems a
> little odd for something that I will use as a Boolean).

Ah yes, the good old "rubbish advice from the internet" strike again.

Unless your faceUp is intended to represent a *three state flag* (say, 
face up, face down, and standing on its side...) then why distinguish 
between None and False? What possible benefit to this is it?

My guess is that they're thinking that setting it to None indicates that 
it is uninitialised. Except that None is a perfectly good falsey value, 
so unless you specifically and carefully change *all* your code that 
currently says:

if self.faceUp: ... 

into:

if self.faceUp is None: raise SomeError
elif self.faceUp: ...

then it makes no difference at all. Just use False and be done with it.


> I have many more similar cases.  For example, in many small game
> programs, at the end of my __init__ method, I call a "reset" method in
> the same class which initializes a bunch of instance variables for
> playing a game.  When the game is over, if the user wants to play again,
> I call the same reset method.  Very clean, and works very well, but all
> the instance variables defined in that reset method gets the same
> warning messages.

Indeed. Linters and code checkers often waste your time warning you 
against things that aren't wrong.



-- 
Steve

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-19 Thread Ben Finney
Irv Kalb  writes:

> In this class, I get warnings on the single lines of the conceal and
> reveal methods.

This is good! It prompts the question: Why are those methods defined as
they are?

If those methods are only ever intended to set the value of an
attribute: Why not just set that attribute directly? (Remember that
Python properties allow you to postpone the decision later of whether
that attribute is a property.)

If those methods are intended to later expand to have side effects: Why
are you calling those methods from the initialiser? The initialiser
should instead just set the initial state of the attributes, avoiding
whatever side-effects are in ‘conceal’ etc.

So, it seems that the warning is correct. The initialiser's job is to
initialise the instance, it should not accidentally invoke a bunch of
side effects. This means the initialiser should tend to just setting
attribute values, not calling a bunch of other methods.

-- 
 \“It is undesirable to believe a proposition when there is no |
  `\   ground whatever for supposing it true.” —Bertrand Russell, _The |
_o__)   Value of Scepticism_, 1928 |
Ben Finney

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-19 Thread Chris Angelico
On Tue, Mar 20, 2018 at 4:25 AM, Ethan Furman  wrote:
> Define them in __init__; otherwise, you get an error if reveal() is called
> before conceal() is.  Also, a card is either revealed or concealed, it can't
> be both and it can't be neither -- so set it in __init__.

__init__ calls conceal.

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-19 Thread Ethan Furman

On 03/19/2018 10:04 AM, Irv Kalb wrote:


I am building some classes for use in future curriculum.  I am using PyCharm 
for my development.  On the right hand edge of the PyCharm editor window, you 
get some little bars indicating warnings or errors in your code.  I like this 
feature and try to clean up as many of those as I can.  However, there is one 
warning that I am seeing often, and I'm not sure about how to handle it.  The 
warning I see is:

"Instance attribute  defined outside of __init__ ..."

The following is a simple example.  I am creating a card class that I am using 
to build card games with PyGame.
class Card():

 BACK_OF_CARD_IMAGE = pygame.image.load('images/backOfCard.png')

 def __init__(self, window, name, suit, value):
 self.window = window
 self.suit = suit
 self.cardName = name + ' of ' + suit
 self.value = value
 fileName = 'images/' + self.cardName + '.png'
 self.image = pygame.image.load(fileName)
 self.backOfCardImage = Card.BACK_OF_CARD_IMAGE

 self.conceal()

 def conceal(self):
 self.faceUp = False

 def reveal(self):
 self.faceUp = True
 

In this class, I get warnings on the single lines of the conceal and reveal methods.  
Yes, the warnings are correct, the variable "self.faceUp" is not defined inside 
the __init__ method.  My __init__ method calls self.conceal which is a more logical place 
to initialize this variable.
My question is, what is the Pythonic way to handle this?  In the research that 
I have done, I see split results.  Some people say that this type of thing is 
fine and these warnings should just be ignored.  While others say that all 
instance variables should be defined in the __init__ method.  I like that idea 
(and have done so in other languages), but if I define this variable there, 
what value should I give it?  Do I redundantly set it to the proper starting 
value (in case False), or do as others have suggested, set it to None (which 
seems a little odd for something that I will use as a Boolean).

I have many more similar cases.  For example, in many small game programs, at the end of 
my __init__ method, I call a "reset" method in the same class which initializes 
a bunch of instance variables for playing a game.  When the game is over, if the user 
wants to play again, I call the same reset method.  Very clean, and works very well, but 
all the instance variables defined in that reset method gets the same warning messages.


Define them in __init__; otherwise, you get an error if reveal() is called before conceal() is.  Also, a card is either 
revealed or concealed, it can't be both and it can't be neither -- so set it in __init__.


As a side note:  I find card_name easier to read than cardName.  :)

--
~Ethan~

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


Re: Style Q: Instance variables defined outside of __init__

2018-03-19 Thread Ned Batchelder

On 3/19/18 1:04 PM, Irv Kalb wrote:

I am building some classes for use in future curriculum.  I am using PyCharm 
for my development.  On the right hand edge of the PyCharm editor window, you 
get some little bars indicating warnings or errors in your code.  I like this 
feature and try to clean up as many of those as I can.  However, there is one 
warning that I am seeing often, and I'm not sure about how to handle it.  The 
warning I see is:

"Instance attribute  defined outside of __init__ ..."

The following is a simple example.  I am creating a card class that I am using 
to build card games with PyGame.
class Card():

 BACK_OF_CARD_IMAGE = pygame.image.load('images/backOfCard.png')

 def __init__(self, window, name, suit, value):
 self.window = window
 self.suit = suit
 self.cardName = name + ' of ' + suit
 self.value = value
 fileName = 'images/' + self.cardName + '.png'
 self.image = pygame.image.load(fileName)
 self.backOfCardImage = Card.BACK_OF_CARD_IMAGE

 self.conceal()

 def conceal(self):
 self.faceUp = False

 def reveal(self):
 self.faceUp = True
 

In this class, I get warnings on the single lines of the conceal and reveal methods.  
Yes, the warnings are correct, the variable "self.faceUp" is not defined inside 
the __init__ method.  My __init__ method calls self.conceal which is a more logical place 
to initialize this variable.
My question is, what is the Pythonic way to handle this?  In the research that 
I have done, I see split results.  Some people say that this type of thing is 
fine and these warnings should just be ignored.  While others say that all 
instance variables should be defined in the __init__ method.  I like that idea 
(and have done so in other languages), but if I define this variable there, 
what value should I give it?  Do I redundantly set it to the proper starting 
value (in case False), or do as others have suggested, set it to None (which 
seems a little odd for something that I will use as a Boolean).


I understand this tension: it's nice to assign only meaningful values, 
and to do it in as few places as possible.  But it's also nice to have 
all of your attributes in one place.  This is a by-product of Python 
having no declarations, only definitions (assignments).  So to mention 
the attributes initially, you have to choose a value for them.  If I 
were to add faceUp to __init__, I would assign False to it.


I have many more similar cases.  For example, in many small game programs, at the end of 
my __init__ method, I call a "reset" method in the same class which initializes 
a bunch of instance variables for playing a game.  When the game is over, if the user 
wants to play again, I call the same reset method.  Very clean, and works very well, but 
all the instance variables defined in that reset method gets the same warning messages.


You didn't ask about this, so perhaps you already know it, but you can 
disable this particular Pylint warning, either line-by-line, 
file-by-file, or for the entire project.


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