Implicit conversion to boolean in if and while statements

S

Steven D'Aprano

Rick said:
Oh really? *chuckles*

Yes, really.

Just because /everything/ in Python is an object does not mean that Python
is 100% OOP. This fact is just one of the many attributes of a 100% OOP
language.

The essential features of OOP style are:

- dynamic dispatch -– Python has this

- encapsulation and/or multi-methods -- Python has this

- subtype polymorphism -- Python has this

- object inheritance or delegation -- Python has both of these

- open recursion (a special variable or keyword, normally called "this"
or "self", that allows method bodies to invoke another method of the same
object -- Python has this

- abstraction -- Python has this

http://en.wikipedia.org/wiki/Object-oriented_programming#Fundamental_features_and_concepts


What does not matter is syntax. Whether you write:

object#method (OCaml)
object->method (C++, Perl, PHP (non-static methods))
object::method (PHP (static methods))
object <- method (E)
[object method] (Objective C)
object:method (Lua)
object.method (Java, Python, VisualBasic)
object method (Smalltalk, some OOP dialects of Forth)
method object (Other OOP dialects of Forth)
object \ method (Pountain Forth)
method(object) (Ada, Dylan, Matlab)
send method to object (Hypertalk, OpenXION)


or something else even more exotic, is entirely irrelevant. What matters is
behaviour, not syntax.


Well you just defeated yourself. How can Python be 100% OOP and then allow
other paradigms?

Your reading comprehension is lacking.

Python allows procedural and functional STYLE syntax. It does not force you
to use a dot out of some slavish attention to an artificial philosophy of
programming language:

http://steve-yegge.blogspot.com.au/2006/03/execution-in-kingdom-of-nouns.html

Python is pragmatic and human-centric. When OOP syntax is best, it will use
OOP syntax. If functional syntax is best, it will wrap objects in a thin
functional layer and use that. If procedural syntax is best, it will use
procedural-style coding. Where a pipeline or flow-based paradigm is best,
Python gives you iterators such as generator expressions. Most of the major
programming paradigms are available in Python, wrapped around a core that
is entirely objects.

NOT IF PYTHON WERE TRULY 100% OOP!

If so, Python would have a supertype called "Collection" that wold define
all methods that operate on collections. Some of these include:

len, any, all, length, isempty, __getitem__, __setitem__, etc...

Then any collection subtype would inherit from this supertype and get the
methods for free.

No they wouldn't. They would inherit an abstract method that raises an
error "Abstract method must be overridden by the subclass" for free.

Do you really think that *every* collection's __getitem__ could possibly use
the *same* implementation?

Should frozenset and set share the same __setitem__?

And what about objects which are not *collections*, and so cannot inherit
from Collection, but still need to implement some of those methods? Strings
are not collections. Should generators be forced to inherit __setitem__ so
that they can share any() and all() methods with lists? What length()
should a lazy generator expression return?

[...]
Using built-in functions to operate on objects is foolish because you are
placing extra burden on the programmer to know which /functions/ work with
which /types/. The *only* functions that should be global are the kind
that will work on *ANY* object. But then again, the Object type could hold
these methods!

If you can remember that lists have a sort() method and floats don't, then
you can remember that sorted() works on lists but not floats.
 
C

Chris Angelico

What the hell? Oh yeah, you must be using pike again. No, if it were pike the list would look like this:

({({"q"}), ({"w","e"}), ({"r","t","u"}), ({"i","o","p"})})

Folks, i couldn't make this stuff up if i wanted to. Go read for yourself if want a few laughs.

You didn't even do a good job of it. Yes, Pike uses two characters
instead of one to wrap array literals. Big friggin' whoop. On the
minus side, it's a little more typing. On the plus side, they stand
out better, and you don't have the [] characters doing double duty
denoting list literals and indexing alike.

Oh, is *THAT* what he meant. I had no idea why it was so laughable.

Another advantage of using two characters: There's no conflict between
set and dict literals. How do you notate an empty set in Python? {}
means an empty dict. In Pike, a mapping is ([]) and a multiset (you
can actually have duplicates, though I don't usually make use of that)
is (<>). But that's a pretty minor design decision, and I wouldn't
laugh at either for the choice. It's like choosing to paint your car
blue or red.

ChrisA
 
D

Dennis Lee Bieber

On Sat, 09 Feb 2013 14:16:59 +1100, Steven D'Aprano
<[email protected]> declaimed the following in
gmane.comp.python.general:

Just for completeness (or, at least, fullness if not completeness)
What does not matter is syntax. Whether you write:

object#method (OCaml)
object->method (C++, Perl, PHP (non-static methods))
object::method (PHP (static methods))
object <- method (E)
[object method] (Objective C)
object:method (Lua)
object.method (Java, Python, VisualBasic)
object method (Smalltalk, some OOP dialects of Forth)
method object (Other OOP dialects of Forth)
object \ method (Pountain Forth)
method(object) (Ada, Dylan, Matlab)

Ada 2005 added designated receiver object.method syntax, though the
function call method(object) is still valid

Object-REXX uses

object~method
 
R

Rick Johnson

[...]
Another advantage of using two characters: There's no conflict between
set and dict literals. How do you notate an empty set in Python? {}
means an empty dict.

What makes you believe that a language must provide literal syntax for EACH and EVERY type? And BTW, if you don't already know, this is how you notate an empty set in Python:

py> set([])
set([])

IMO "Set Types" should only exists as a concequence of "freezing" an array, and should have NO literal syntax avaiable.
 
R

Rick Johnson

[...]
Another advantage of using two characters: There's no conflict between
set and dict literals. How do you notate an empty set in Python? {}
means an empty dict.

What makes you believe that a language must provide literal syntax for EACH and EVERY type? And BTW, if you don't already know, this is how you notate an empty set in Python:

py> set([])
set([])

IMO "Set Types" should only exists as a concequence of "freezing" an array, and should have NO literal syntax avaiable.
 
C

Chris Angelico

[...]
Another advantage of using two characters: There's no conflict between
set and dict literals. How do you notate an empty set in Python? {}
means an empty dict.

What makes you believe that a language must provide literal syntax for EACH and EVERY type? And BTW, if you don't already know, this is how you notate an empty set in Python:

py> set([])
set([])

Or omit the argument, to avoid working with a pointless empty list.
But what happens if you first execute:

set = tuple

? This is not a set literal, it's an expression that usually returns a set.
IMO "Set Types" should only exists as a concequence of "freezing" an array, and should have NO literal syntax avaiable.

I don't understand. Wouldn't freezing an array (list) result in a
tuple? And, why should there be no literal syntax for them?

Having a convenient literal notation for every basic type is extremely
handy. You can work with integers 1, 2, 3, or floats 1.0, 2.0, 3.0. C
gives you those. In Python, you can work with lists, too, and C
doesn't give you those (you have array *initializer* syntax, but
that's not the same thing). It's perfectly plausible to dereference a
literal:

dow = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][day%7]

Of course, it's perfectly plausible to do that with a function, too.
You could define something like this:

def agg(*args): return args
dow = agg("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")[day%7]

But the question is, why? Why call a function when the interpreter can
do the work directly at compile stage? There's absolutely no value in
forcing things to be done at run-time.

ChrisA
 
R

Rick Johnson

Actually, that's not a declaration, that's an assignment; and in Pike,
a 'type' is a thing, same as it is in Python (though not quite). If I
were to declare it in Pike, it would be:

array(array(string)) nested_list;

Though the part inside the parens can be omitted, in which case the
array can contain anything, rather than being restricted to strings.
In actual fact, Rick, despite your complaints about the syntax, it's
able to achieve exactly what you were thinking Python should do:
declare an array/list that contains only numbers.

Well Chris i have wonderful news for you! Python /does/ have "homogenous arrays", and they're called, wait for it......... arrays! Imagine that!

py> import array
py> intSeq = array.array('i')
py> intSeq.append(1)
py> intSeq.append(2)
py> intSeq.append(5000)
py> intSeq.append(5000.333)
TypeError: integer argument expected, got float
py> intSeq.append('5000.333')
TypeError: an integer is required
 
R

Rick Johnson

Actually, that's not a declaration, that's an assignment; and in Pike,
a 'type' is a thing, same as it is in Python (though not quite). If I
were to declare it in Pike, it would be:

array(array(string)) nested_list;

Though the part inside the parens can be omitted, in which case the
array can contain anything, rather than being restricted to strings.
In actual fact, Rick, despite your complaints about the syntax, it's
able to achieve exactly what you were thinking Python should do:
declare an array/list that contains only numbers.

Well Chris i have wonderful news for you! Python /does/ have "homogenous arrays", and they're called, wait for it......... arrays! Imagine that!

py> import array
py> intSeq = array.array('i')
py> intSeq.append(1)
py> intSeq.append(2)
py> intSeq.append(5000)
py> intSeq.append(5000.333)
TypeError: integer argument expected, got float
py> intSeq.append('5000.333')
TypeError: an integer is required
 
C

Chris Angelico

Well Chris i have wonderful news for you! Python /does/ have "homogenous arrays", and they're called, wait for it......... arrays! Imagine that!

That's not a built-in. But you were the one who complained about the
way sum() could be applied to a list that contains a non-integer;
maybe your solution is simply to ignore sum() and work with
array.array?

Nice how you can complain about Python for not having something, then
heap scorn on me for not being aware that it's there in the stdlib.
(Which, by the way, I freely admit to being less than fully familiar
with. Even less familiar with what's on PyPI.)

ChrisA
 
R

Rick Johnson

I'm a bit unnerved by the sum function. Summing a
sequence only makes sense if the sequence in question
contains /only/ numeric types. For that reason i decided
to create a special type for holding Numerics.
[...]
Of course someone could
probably find a legitimate reason to apply a sum method
to non-numeric values; if so, then inherit from
NumericSequence and create your custom type!

Are you aware that the approach you're advocating here is bad OOP
design? If you declare a class NumericSequence with the property that
it contains only numeric types, and then you declare a subclass
NonnumericSequence that does not share that property, then guess what?
You've just violated the Liskov Substitution Principle.

I totally agree! Really, no sarcasm here O:)

Not only because we would be attempting to bend a numeric type into something it is not, but even more foolishly because the very method we hope to gain (sum) would need to be completely re-written anyway. I must have lost myself in the rant because that was a foolish thing to say. Thanks for pointing this out.
The goal you're trying to achieve here is nonsensical anyway. Ask
yourself what the semantic meaning of the sum() function is, what
purpose it is meant to serve. My answer: it is the reduction of the
addition operator.

I think that for Numeric Types your answer is spot on! And i'll bet if we ruminated long enough we could probably find a few more transformations of the word "sum" into unique contexts. But i digress, we'll have to save that synergy for a time when you are buying the beer! ;-)
The implication of this is that the input type of
the sum() function is not "numbers", but rather "things that can be
added".

Indeed. Contrary to what a few folks have stated in this thread, if two different objects have methods named "sum", that does NOT mean that we have broken the fine principles of "code reuse", no. Why? Because two methods named "sum" can contain completely different code! Yes, i know that's difficultfor some to believe, but it's the truth!

Consider a sum method of a "Numeric Type" compared to the sum method of a "Sequence Type". Not only is the algorithm different, but the result is different. Summing N numerics requires utilizing the strict rules of mathematical addition, keeping a running total, and returning a type (Integer) that is different from the input type, whereas summing sequences requires expanding the first sequence with the values of the second sequence (all whilst maintaining linear order) and returning a new instance of the same type (f.e.list).

Of course you could write a single monolithic function that can operate on multiple types transparently (*cough* saum!) however:

* Nobody can predict the future (at least not yet) so you
will eventually encounter a new type that breaks the
god @#$% function.

* Your language will rely on "magic", thereby confusing
it's users, with well, magic!

* But most disappointing of all: you will break the accepted
OOP convention of encapsulation, whereby the object
/itself/ should operate on the data, not some outside god
@#$% function!

But let's dig a little deeper here so we might understand /why/ encapsulation is /so/ gawd @#$%ed important to OOP.

Why do we prefer objects to operate on their own data rather than some "magical-all-knowing-god-like-creature-from-another-planet-who-thinks-his-bowel-movements-smell-like-bakery-fresh-cinnamon-rolls? Is it because we want objects to feel a sense of "belonging" or "importance"? ...OF COURSE NOT! Objects neither think nor feel!

We employ encapsulation because by doing so we keep all the relevant code under one class, one module, one package. By doing so we create a hierarchy;and since hierarchies are much easier to search than random sequences, we will thank ourselves later!

If you want a fine example of this consider a list and a dict object. If you want to find a value in a list you are forced to search the entire list "item-by-item" until you find a match; there are NO shortcuts here! However,when we have data in a dict all we need is a key, and voila!, we have a direct path to the item! Same applies to code.

RR: "GOOD paradigms solve problems when /writing/ code, GREAT paradigms solve problems when writing and /maintaining/ code!"
That includes numbers, but since I see from your proposed
class hierarchy that you are retaining the __add__ method on
sequences, it also includes sequences. Are you really going to tell
the user that (1, 2, 3) + (4, 5, 6) is perfectly fine, but that the
semantic equivalent sum([(1, 2, 3), (4, 5, 6)]) is nonsense?

Yes. Because if the user has a problem understanding /why/ adding two sequences together results in a new sequence and /not/ a number, he can simply open the source for the Sequence object, locate the sum method, and read code that is ONLY RELEVANT TO SUMMING A SEQUENCE OBJECT. [1]

Whereas with a global function --which has been whored-out to operate on many types, and will probably include a massive conditional!-- he will need to read through many lines of irrelevant code just to find the relevant code, then /hopefully/ he has the cognitive power remaining to find the answer.

[1] Of course this is not the /only/ reason why encapsulation is so important.
 
R

Rick Johnson

I'm a bit unnerved by the sum function. Summing a
sequence only makes sense if the sequence in question
contains /only/ numeric types. For that reason i decided
to create a special type for holding Numerics.
[...]
Of course someone could
probably find a legitimate reason to apply a sum method
to non-numeric values; if so, then inherit from
NumericSequence and create your custom type!

Are you aware that the approach you're advocating here is bad OOP
design? If you declare a class NumericSequence with the property that
it contains only numeric types, and then you declare a subclass
NonnumericSequence that does not share that property, then guess what?
You've just violated the Liskov Substitution Principle.

I totally agree! Really, no sarcasm here O:)

Not only because we would be attempting to bend a numeric type into something it is not, but even more foolishly because the very method we hope to gain (sum) would need to be completely re-written anyway. I must have lost myself in the rant because that was a foolish thing to say. Thanks for pointing this out.
The goal you're trying to achieve here is nonsensical anyway. Ask
yourself what the semantic meaning of the sum() function is, what
purpose it is meant to serve. My answer: it is the reduction of the
addition operator.

I think that for Numeric Types your answer is spot on! And i'll bet if we ruminated long enough we could probably find a few more transformations of the word "sum" into unique contexts. But i digress, we'll have to save that synergy for a time when you are buying the beer! ;-)
The implication of this is that the input type of
the sum() function is not "numbers", but rather "things that can be
added".

Indeed. Contrary to what a few folks have stated in this thread, if two different objects have methods named "sum", that does NOT mean that we have broken the fine principles of "code reuse", no. Why? Because two methods named "sum" can contain completely different code! Yes, i know that's difficultfor some to believe, but it's the truth!

Consider a sum method of a "Numeric Type" compared to the sum method of a "Sequence Type". Not only is the algorithm different, but the result is different. Summing N numerics requires utilizing the strict rules of mathematical addition, keeping a running total, and returning a type (Integer) that is different from the input type, whereas summing sequences requires expanding the first sequence with the values of the second sequence (all whilst maintaining linear order) and returning a new instance of the same type (f.e.list).

Of course you could write a single monolithic function that can operate on multiple types transparently (*cough* saum!) however:

* Nobody can predict the future (at least not yet) so you
will eventually encounter a new type that breaks the
god @#$% function.

* Your language will rely on "magic", thereby confusing
it's users, with well, magic!

* But most disappointing of all: you will break the accepted
OOP convention of encapsulation, whereby the object
/itself/ should operate on the data, not some outside god
@#$% function!

But let's dig a little deeper here so we might understand /why/ encapsulation is /so/ gawd @#$%ed important to OOP.

Why do we prefer objects to operate on their own data rather than some "magical-all-knowing-god-like-creature-from-another-planet-who-thinks-his-bowel-movements-smell-like-bakery-fresh-cinnamon-rolls? Is it because we want objects to feel a sense of "belonging" or "importance"? ...OF COURSE NOT! Objects neither think nor feel!

We employ encapsulation because by doing so we keep all the relevant code under one class, one module, one package. By doing so we create a hierarchy;and since hierarchies are much easier to search than random sequences, we will thank ourselves later!

If you want a fine example of this consider a list and a dict object. If you want to find a value in a list you are forced to search the entire list "item-by-item" until you find a match; there are NO shortcuts here! However,when we have data in a dict all we need is a key, and voila!, we have a direct path to the item! Same applies to code.

RR: "GOOD paradigms solve problems when /writing/ code, GREAT paradigms solve problems when writing and /maintaining/ code!"
That includes numbers, but since I see from your proposed
class hierarchy that you are retaining the __add__ method on
sequences, it also includes sequences. Are you really going to tell
the user that (1, 2, 3) + (4, 5, 6) is perfectly fine, but that the
semantic equivalent sum([(1, 2, 3), (4, 5, 6)]) is nonsense?

Yes. Because if the user has a problem understanding /why/ adding two sequences together results in a new sequence and /not/ a number, he can simply open the source for the Sequence object, locate the sum method, and read code that is ONLY RELEVANT TO SUMMING A SEQUENCE OBJECT. [1]

Whereas with a global function --which has been whored-out to operate on many types, and will probably include a massive conditional!-- he will need to read through many lines of irrelevant code just to find the relevant code, then /hopefully/ he has the cognitive power remaining to find the answer.

[1] Of course this is not the /only/ reason why encapsulation is so important.
 
S

Steven D'Aprano

Rick said:
IMO "Set Types" should only exists as a concequence of "freezing" an
array,

Sets are not frozen lists.
and should have NO literal syntax avaiable.

Unfortunately, Python has a minor design flaw. One of the most common
use-cases for sets is for membership testing of literal sets:

def example(arg):
if arg in {'spam', 'ham', 'eggs', 'cheese'}:
...

Unfortunately, set literals create *mutable* sets, not frozensets. That
means that the compiler wastes time and memory creating am over-allocated
mutable set object. If set literals created immutable frozensets, there
would be some nice opportunities for the compiler to optimize this
use-case.

So, in Python 4000, my vote is for set literals { } to create frozensets,
and if you want a mutable set, you have to use the set() type directly.
 
T

Thomas Rachel

Am 10.02.2013 12:37 schrieb Steven D'Aprano:
So, in Python 4000, my vote is for set literals { } to create frozensets,
and if you want a mutable set, you have to use the set() type directly.

4000 sounds about long future.

In the meanwhile, a new syntax element could be introduced fpr
frozensets, such as {{ }} or something. (Although that might clutter
with a set containing a set.)


Thomas
 
R

Rick Johnson

[...]
I don't understand. Wouldn't freezing an array (list) result in a
tuple? And, why should there be no literal syntax for them?

Having a convenient literal notation for every basic type is extremely
handy.

Actually i must admit that you are correct. Of course the problem with literal syntax is symbol congestion. But i have a solution. A solution that cansurvive the limited number of grouping chars that python employs now. Except, i will define them explicitly

{}: denotes ANY mapping object.
[]: denotes ANY mutable sequence object.
(): denotes ANY immutable sequence object.
<>: Hmm, there must be a good use for this one!

The key to removing complexity is to declare the literal syntax much the way Python "represents" a "set". Observe:

py> set([1,2,3])
set([1,2,3])

Using this syntax we can apply "grouping" chars in proper context when writing literal syntax. The only problem is how do we make this syntax unique enough to avoid confusion and complexity??? Some hypothetical literal syntax, "syntaxes", include:

<set>[1,2,3] # Set literal
<set>(1,2,3) # FrozenSet literal

set=>[1,2,3] # Set literal
set=>(1,2,3) # FrozenSet literal

set::[1,2,3] # Set literal
set::(1,2,3) # FrozenSet literal

set<[1,2,3]> # Set literal
set<(1,2,3)> # FrozenSet literal

<set[1,2,3]> # Set literal
<set(1,2,3)> # FrozenSet literal

set([1,2,3]) # Set literal
set((1,2,3)) # FrozenSet literal


....and to avoid conflicts with the "set" function, we just remove the set function! Only the types list, dict, and tuple(bka:StaticList!) should have a built-in constructor function, the remaining should have a typical OOP style constructor:

mySet = Set([1,2,3])
mySetLiteral = set([1,2,3])
 
R

Rick Johnson

[...]
I don't understand. Wouldn't freezing an array (list) result in a
tuple? And, why should there be no literal syntax for them?

Having a convenient literal notation for every basic type is extremely
handy.

Actually i must admit that you are correct. Of course the problem with literal syntax is symbol congestion. But i have a solution. A solution that cansurvive the limited number of grouping chars that python employs now. Except, i will define them explicitly

{}: denotes ANY mapping object.
[]: denotes ANY mutable sequence object.
(): denotes ANY immutable sequence object.
<>: Hmm, there must be a good use for this one!

The key to removing complexity is to declare the literal syntax much the way Python "represents" a "set". Observe:

py> set([1,2,3])
set([1,2,3])

Using this syntax we can apply "grouping" chars in proper context when writing literal syntax. The only problem is how do we make this syntax unique enough to avoid confusion and complexity??? Some hypothetical literal syntax, "syntaxes", include:

<set>[1,2,3] # Set literal
<set>(1,2,3) # FrozenSet literal

set=>[1,2,3] # Set literal
set=>(1,2,3) # FrozenSet literal

set::[1,2,3] # Set literal
set::(1,2,3) # FrozenSet literal

set<[1,2,3]> # Set literal
set<(1,2,3)> # FrozenSet literal

<set[1,2,3]> # Set literal
<set(1,2,3)> # FrozenSet literal

set([1,2,3]) # Set literal
set((1,2,3)) # FrozenSet literal


....and to avoid conflicts with the "set" function, we just remove the set function! Only the types list, dict, and tuple(bka:StaticList!) should have a built-in constructor function, the remaining should have a typical OOP style constructor:

mySet = Set([1,2,3])
mySetLiteral = set([1,2,3])
 
A

alex23

That's a strange thing to say when you go on to provide an example that tests the validity of the object "each and every time":

Here's a tip: context is important. I was referring to not having to
*explicitly* test if a label *is defined* in order to be able to use
it, which is something you need to do in other languages, such as
Javascript:

var func = function() { throw EventException; }
a = func()
if ( a == '1') ... // this raises a ReferenceError as 'a' is not
defined
if ( typeof a !== 'undefined' && a == '1')... // this guards
against the ReferenceError
And i find it to be incredibly asinine.

I find your smugness to be much the same.
Consider this:
    if connect("my:db") as db:
        <do something>

No need to make a call and then test for the validity of the call when you can do both simultaneously AND intuitively.

No need to learn a language when you can just make crap up and whine
when it doesn't work.
*school-bell-rings*

You're "schooling" others using a hypothetical variant of an existing
language which you believe should conform to your a priori assumptions
about how such a language should work? You're "schooling" people who
_read the documentation_ when you admit to not doing so yourself?

You're not asinine, you're just an asshole.
 
R

Rick Johnson

Sets are not frozen lists.

Indeed. That wording was a bit clumsy on my part.

I may have spoken too soon on this issue. My reasoning for /not/ having a literal set syntax was due to symbol congestion, however as i described in another post, the problem can be solved by literally "type declaring" the literal.
 
R

Rick Johnson

That's not a built-in. But you were the one who complained about the
way sum() could be applied to a list that contains a non-integer;
maybe your solution is simply to ignore sum() and work with
array.array?

Yes i could, however by doing so i would be ignoring the inconsistent elephant in the room. My crusade is to bring consistency and logic to languages,and if i have any free time afterwards, to remove multiplicity. There are two types of people in the world Chris, those that lead and those that follow.
Nice how you can complain about Python for not having something, then
heap scorn on me for not being aware that it's there in the stdlib.
(Which, by the way, I freely admit to being less than fully familiar
with. Even less familiar with what's on PyPI.)

Well i would expect anyone who considers himself a python programmer (not to mention "pythonista"!) to at minimum be familiar with the stdlib. That does not mean he must have attained black belt level kung-fu in /every/ stdlib module, but he must at least /know/ all the modules names and all types that Python offers. Is that really too much to ask Chris?
 
R

Rick Johnson

That's not a built-in. But you were the one who complained about the
way sum() could be applied to a list that contains a non-integer;
maybe your solution is simply to ignore sum() and work with
array.array?

Yes i could, however by doing so i would be ignoring the inconsistent elephant in the room. My crusade is to bring consistency and logic to languages,and if i have any free time afterwards, to remove multiplicity. There are two types of people in the world Chris, those that lead and those that follow.
Nice how you can complain about Python for not having something, then
heap scorn on me for not being aware that it's there in the stdlib.
(Which, by the way, I freely admit to being less than fully familiar
with. Even less familiar with what's on PyPI.)

Well i would expect anyone who considers himself a python programmer (not to mention "pythonista"!) to at minimum be familiar with the stdlib. That does not mean he must have attained black belt level kung-fu in /every/ stdlib module, but he must at least /know/ all the modules names and all types that Python offers. Is that really too much to ask Chris?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top