Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #94542 > unrolled thread
| Started by | Laura Creighton <lac@openend.se> |
|---|---|
| First post | 2015-07-25 13:01 +0200 |
| Last post | 2015-07-26 12:35 +0200 |
| Articles | 8 — 2 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: scalar vs array and program control Laura Creighton <lac@openend.se> - 2015-07-25 13:01 +0200
Re: scalar vs array and program control Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-07-25 14:57 +0200
Re: scalar vs array and program control Laura Creighton <lac@openend.se> - 2015-07-25 15:43 +0200
Re: scalar vs array and program control Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-07-25 18:53 +0200
Re: scalar vs array and program control Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-07-25 18:56 +0200
Re: scalar vs array and program control Laura Creighton <lac@openend.se> - 2015-07-25 19:45 +0200
Re: scalar vs array and program control Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-07-26 12:26 +0200
Re: scalar vs array and program control Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-07-26 12:35 +0200
| From | Laura Creighton <lac@openend.se> |
|---|---|
| Date | 2015-07-25 13:01 +0200 |
| Subject | Re: scalar vs array and program control |
| Message-ID | <mailman.973.1437822101.3674.python-list@python.org> |
You have a bit of a problem, in that "functional" and "object-oriented"
are two different styles of programming. You really cannot make your
code 'more functional' and 'more object-oriented' at the same time --
more in one style implies less in the other. I think you may have
got the mistaken idea that 'object-orientated' means 'well-written'
or 'professional' or some such.
However, if your intuition was telling you that it would be bad to
write code that goes:
if type(x) is str:
do_something()
elif type(x) is float:
do_something_else()
elif type(x) is int:
do_another_thing()
else:
scream_loudly_and_dont_do_anything()
then your intuition is working perfectly. Don't stick typechecks in all
over your code. It makes it fragile and hard to maintain. It also means
that you have to anticipate all the perfectly good input you might have,
and nobody can do that.
For instance, might somebody want to feed your functions complex numbers
one day? Or, here is a good one -- python has a Decimal datatype
which does Decimal floating point arithmetic. You don't want your code
to not work for people using Decimal numbers just because you didn't
put in a check for
>>> type(Decimal(10.5))
<class 'decimal.Decimal'>
If you find you need to check the type of something, it is better to use
the isinstance function.
if isinstance(x, str):
do something()
else:
do_something_else()
The python builtin types are all included here. For the sort of work
you do it is useful to know about
from numbers import Number
isinstance(x, Number)
which will happily return True for all sorts of numbers, complex,
Decimal numbers even number classes which you define yourself.
So if you need to do this sort of 'look before you leap' checking,
isinstance is the way to do it. And sometimes this _is_ the sort of
checking you want to do. But, aside from when you are writing test
code, where it happens all over the place, most of the type in writing
Python code we don't do this either.
We don't look before we leap. We leap, and then if there are any
problems, we deal with it.
Instead we do something like this:
consider a function that converts a string to a number
def string_to_number(s):
try:
return int(s)
except ValueError:
return float(s)
If all your input is guaranteed to be ints or floats this will work fine.
It also works if you feed it things that are already ints and floats
(not strings). And this is nice .
How did I know to look for ValueErrors?
>>> int("1.2")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '1.2'
Cause that is what Python gives you. If it had given you a TypeError
instead -- which is what I expected it to do, but so it goes -- I
would have said except TypeError.
You can stack these things.
>>>
def string_to_number(x):
try:
return int(x)
except ValueError:
try:
return float(x)
except ValueError:
return complex(x)
So now it handles complex numbers as well.
So this is, quite likely, the pattern that you are looking for:
try:
all_your_code_which_is_happy_with_non_scalars
except WhateverErrorPythonGivesYouWhenYouTryThisWithScalars:
whatever_you_want_to_do_when_this_happens
This is the usual way to do things.
If you find that your try/except pairs are walking themselves all the
way to the right hand side of the screen it is time to consider
restructuring your code.
The great advantage of this approach is that you don't have to
pretend to omniscience about the sort of input you will get. If I
decide to call your code with an array of Decimal floating point
integers instead of regular floats, it's great if it just works,
whether or not you had the idea of Decimal floating point in mind
when you wrote the code.
Sorry to be so longwinded. I need to go now and don't have time to
revise it, though it probably should be made a whole bunch less
preachy.
Hope it helps,
Laura
[toc] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-07-25 14:57 +0200 |
| Message-ID | <1619647.1FW7hyz6Jq@PointedEars.de> |
| In reply to | #94542 |
Laura Creighton wrote: > […] You really cannot make your code 'more functional' and 'more object- > oriented' at the same time -- more in one style implies less in the other. How did you get that idea? -- PointedEars Twitter: @PointedEars2 Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Laura Creighton <lac@openend.se> |
|---|---|
| Date | 2015-07-25 15:43 +0200 |
| Message-ID | <mailman.978.1437831852.3674.python-list@python.org> |
| In reply to | #94547 |
In a message of Sat, 25 Jul 2015 14:57:14 +0200, "Thomas 'PointedEars' Lahn" wr ites: >Laura Creighton wrote: > >> […] You really cannot make your code 'more functional' and 'more object- >> oriented' at the same time -- more in one style implies less in the other. > >How did you get that idea? Because pure object oriented techniques are best when you have a fixed set of operations on things, and as your code evolves you primarily add new things. Things written in a functional style work best when you have a fixed set of things, and your code evolves you add new operations for the existing things. Laura
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-07-25 18:53 +0200 |
| Message-ID | <1757573.rN60lcJNyZ@PointedEars.de> |
| In reply to | #94550 |
Laura Creighton wrote:
> […] "Thomas 'PointedEars' Lahn" [writes]:
>> Laura Creighton wrote:
>>> […] You really cannot make your code 'more functional' and 'more
>>> object-oriented' at the same time -- more in one style implies less
>>> in the other.
>> How did you get that idea?
>
> Because pure object oriented techniques are best when you have
> a fixed set of operations on things, and as your code evolves
> you primarily add new things. Things written in a functional style
> work best when you have a fixed set of things, and your code evolves
> you add new operations for the existing things.
Your logic is flawed. “*Pure* object oriented” is your raising the bar.
First of all, object-oriented programming and functional programming are
programming *paradigms*, not merely techniques. Second, they are _not_
mutually exclusive paradigms. Third, Python supports both because in
Python, functions are first-class objects. (In fact, if I am not mistaken,
everything except None is an object in Python.)
For example, let us make this original Python code more object-oriented and
more functional at the same time:
#------------------------------------------------------------------------
def foo (a, b):
return a + b
print(foo(42, 23))
#------------------------------------------------------------------------
First, more functional:
#------------------------------------------------------------------------
def foo (f, a, b):
return f(a, b)
print(foo(lambda a, b: return a + b, 42, 23))
#------------------------------------------------------------------------
Instead of hard-coding the “+” operation, (a reference to) a function
(object) can be passed that is passed the remaining arguments, and the
return value of the function is returned instead (you could overload the
operator, and the “foo” call here could be inlined, of course; this is just
an example).
Second, more object-oriented:
#------------------------------------------------------------------------
class A:
def __init__ (self, v=0):
self._value = v
def foo (self, f, b):
return f(f, self._value, b)
print(A(42).foo(lambda a, b: return a + b, 23))
#------------------------------------------------------------------------
The first operand now is an object, an instance of a class, and the former
“foo” function has become a method of that class that the object inherits.
The method could be further inherited from a superclass, or overwritten by a
subclass, for polymorphism. The callback could also be a public method
provided by a class.
There are probably better examples. In any case it should be possible for
you to see that you are mistaken: One *can* make code more functional and
more object-oriented at the same time, and more in one "style" does _not_
imply less in the other.
--
PointedEars
Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-07-25 18:56 +0200 |
| Message-ID | <3271934.brgO5pjKeM@PointedEars.de> |
| In reply to | #94559 |
Thomas 'PointedEars' Lahn wrote:
> #------------------------------------------------------------------------
> class A:
> def __init__ (self, v=0):
> self._value = v
>
> def foo (self, f, b):
> return f(f, self._value, b)
I mean
return f(self._value, b)
--
PointedEars
Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Laura Creighton <lac@openend.se> |
|---|---|
| Date | 2015-07-25 19:45 +0200 |
| Message-ID | <mailman.989.1437846349.3674.python-list@python.org> |
| In reply to | #94559 |
In a message of Sat, 25 Jul 2015 18:53:33 +0200, "Thomas 'PointedEars' Lahn" wr ites: >Laura Creighton wrote: > >> […] "Thomas 'PointedEars' Lahn" [writes]: >>> Laura Creighton wrote: >>>> […] You really cannot make your code 'more functional' and 'more >>>> object-oriented' at the same time -- more in one style implies less >>>> in the other. >>> How did you get that idea? >> >> Because pure object oriented techniques are best when you have >> a fixed set of operations on things, and as your code evolves >> you primarily add new things. Things written in a functional style >> work best when you have a fixed set of things, and your code evolves >> you add new operations for the existing things. > >Your logic is flawed. “*Pure* object oriented” is your raising the bar. Yes. But I could have said, and probably should have said 'pure functional style' as well. >First of all, object-oriented programming and functional programming are >programming *paradigms*, not merely techniques. Second, they are _not_ >mutually exclusive paradigms. Third, Python supports both because in >Python, functions are first-class objects. (In fact, if I am not mistaken, >everything except None is an object in Python.) Ah, digression here. I generalise between paradigms that generate useful techniques, (functional programming and object oriented programming both do this) and those that do not (the Marxist paradigm of the labour theory of value). It still may be very useful and instructive to think on the Marxist Labour Theory of value, and it may have new utility if we can replace all labour with computer/robotic/IT ... but for now, do not run your economy on this theory, ok, because it does not work.) Second digression: that a thing uses objects does not make the thing more object oriented. >For example, let us make this original Python code more object-oriented and >more functional at the same time: > >#------------------------------------------------------------------------ >def foo (a, b): > return a + b > >print(foo(42, 23)) >#------------------------------------------------------------------------ > >First, more functional: > >#------------------------------------------------------------------------ >def foo (f, a, b): > return f(a, b) > >print(foo(lambda a, b: return a + b, 42, 23)) >#------------------------------------------------------------------------ > >Instead of hard-coding the “+” operation, (a reference to) a function >(object) can be passed that is passed the remaining arguments, and the >return value of the function is returned instead (you could overload the >operator, and the “foo” call here could be inlined, of course; this is just >an example). >Second, more object-oriented: > >#------------------------------------------------------------------------ >class A: > def __init__ (self, v=0): > self._value = v > > def foo (self, f, b): > return f(f, self._value, b) > >print(A(42).foo(lambda a, b: return a + b, 23)) >#------------------------------------------------------------------------ > >The first operand now is an object, an instance of a class, and the former >“foo” function has become a method of that class that the object inherits. >The method could be further inherited from a superclass, or overwritten by a >subclass, for polymorphism. The callback could also be a public method >provided by a class. > >There are probably better examples. In any case it should be possible for >you to see that you are mistaken: One *can* make code more functional and >more object-oriented at the same time, and more in one "style" does _not_ >imply less in the other. Okay, I give. It's possible, and I overstated things. But I suspect that it is only possible in things that are in the behavioural middle. You needed a lambda to make the thing more functional, and to create a class where none was before to make it more object-oriented. But this means that the thing wasn't all that functional nor object-oriented -- most likely procedural -- to start with. So, very clever. But still the general rule in refactoring, is that you want to go more oo or more functional, not both at the same time. Laura
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-07-26 12:26 +0200 |
| Message-ID | <1852361.ZT26voajJO@PointedEars.de> |
| In reply to | #94566 |
Laura Creighton wrote: > […] "Thomas 'PointedEars' Lahn" writes: >> Laura Creighton wrote: >>> […] "Thomas 'PointedEars' Lahn" [writes]: >>>> Laura Creighton wrote: >>>>> […] You really cannot make your code 'more functional' and 'more >>>>> object-oriented' at the same time -- more in one style implies less >>>>> in the other. >>>> How did you get that idea? >>> Because pure object oriented techniques are best when you have >>> a fixed set of operations on things, and as your code evolves >>> you primarily add new things. Things written in a functional style >>> work best when you have a fixed set of things, and your code evolves >>> you add new operations for the existing things. >> Your logic is flawed. “*Pure* object oriented” is your raising the bar. > > Yes. But I could have said, and probably should have said 'pure > functional style' as well. That would not have changed anything. It is the “pure” that makes your argument fallacious. The “pure” falsely implies that you cannot have both at the same time, that you can have either function or object-oriented code. And ISTM that you are extending on the questionable idea that only “pure” is “good” to say that it would be inadvisable to have both at the same time. That is circular, for *that* property alone fallacious, logic. >>First of all, object-oriented programming and functional programming are >>programming *paradigms*, not merely techniques. Second, they are _not_ >>mutually exclusive paradigms. Third, Python supports both because in >>Python, functions are first-class objects. (In fact, if I am not >>mistaken, everything except None is an object in Python.) > > Ah, digression here. I generalise between paradigms that generate > useful techniques, (functional programming and object oriented programming > both do this) and those that do not (the Marxist paradigm of the > labour theory of value). You may not find them useful; several other people do. > It still may be very useful and instructive to think on the Marxist Labour > Theory of value, and it may have new utility if we can replace all labour > with computer/robotic/IT ... but for now, do not run your economy on this > theory, ok, because it does not work.) Trollish nonsense. Leave politics outside the door, it has nothing to do with this. > Second digression: that a thing uses objects does not make the thing > more object oriented. Yes, it does. That is the very definition of *object*-*oriented*. > But I suspect that it is only possible in things that are in > the behavioural middle. Now you are making up terminology. > You needed a lambda to make the thing more functional, I did not; it was merely a better visible shortcut, for a lambda expression is obviously a part of functional programming. I could have defined a function instead and used the function identifier, and AISB I could also have used a reference to a method of an object. The functional aspect of it was not the “lambda” but that I passed (a reference to) a function (a lambda expression is an inline function definition). That is only possible if functions are first-class objects, meaning that they can be rvalues [sic] (“object” is not necessarily to be understood as the “object” in OOP, but for several programming languages, including Python, the other meaning applies as well; I used the term too loosely in my previous followup). > and to create a class where none was before to make it more object- > oriented. I did not need to, but, again, it was more obvious that way. I could also have used an existing class, and its existing or newly added method. AISB, almost everything in Python is an object; therefore, almost everything in Python has a class (try “print((42)).__class__)” in Py3k). And Python is not the only object-oriented programming language for which this is true. Other object-oriented programming languages, for example ECMAScript implementations (which are my primary research topic), still have primitive values as well, but those are implicitly converted into object values when OOP patterns are used, and then those objects inherit properties as well. > But this means that the thing wasn't all that> functional nor object- > oriented -- most likely procedural -- to start with. Obviously nonsense. The procedural programming paradigm is neither the antithesis of the functional nor of the object-oriented programming one. > So, very clever. But still the general rule in refactoring, is that > you want to go more oo or more functional, not both at the same time. Nonsense. You are projecting your misconceptions and ignorance (of Python, and programming paradigms in general) onto others. -- PointedEars Twitter: @PointedEars2 Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-07-26 12:35 +0200 |
| Message-ID | <2035096.cBO6vpb5vr@PointedEars.de> |
| In reply to | #94615 |
Thomas 'PointedEars' Lahn wrote:
> Laura Creighton wrote:
>> and to create a class where none was before to make it more object-
>> oriented.
>
> I did not need to, but, again, it was more obvious that way. I could also
> have used an existing class, and its existing or newly added method.
> AISB, almost everything in Python is an object; therefore, almost
> everything in Python has a class (try “print((42)).__class__)” in Py3k).
^
> […]
| >>> print((42).__class__)
| <class 'int'>
Most interesting (but understandable):
| >>> print(42..__class__)
| <class 'float'>
BTW, another common misconception that I read from your argument is that
“object-oriented” would be synonymous with “class-based”; that one needs a
class for OOP. In fact, however, there are several object-oriented
programming languages, again for example most ECMAScript implementations,
that are prototype-based: one object/instance inherits from another, its
prototype.
--
PointedEars
Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web