Can somebody give me an advice about what to learn?

T

tcgo

Hi!
I'm really new to Usenet/Newsgroups, but... I'd like to learn some new programming language, because I learnt a bit of Perl though its OOP is ugly. So, after searching a bit, I found Python and Ruby, and both of they are cute.
So, assuming you'll say me "learn python", why should I learn it over Ruby?
Thanks!
PS: I don't want to start a flame-war, I just want an advice if it's possible please!
 
C

Chris Angelico

Hi!
I'm really new to Usenet/Newsgroups, but... I'd like to learn some new programming language, because I learnt a bit of Perl though its OOP is ugly. So, after searching a bit, I found Python and Ruby, and both of they are cute.
So, assuming you'll say me "learn python", why should I learn it over Ruby?
Thanks!
PS: I don't want to start a flame-war, I just want an advice if it's possible please!

I'm not going to touch Ruby, partly because I don't know it, and
partly to avoid a flame war, but here's some good reasons to learn
Python:

* It's a modern, object-oriented, high level language.
* As of version 3.3 (do make sure you grab this one, there's lots of
enhancements), it has absolutely correct AND efficient Unicode string
handling. I know of only one other language that can store "Hello" as
a five-byte string, while simultaneously allowing perfect handling of
the entire Unicode range.
* Python's syntax is clean and easy to handle. Be aware, though, that
some things are distinctly different from C-family languages.
* You get an excellent set of modules. Python has "batteries included"
(the standard library is extensive) and a whole set of custom
batteries on speed dial (check out PyPI).
* Easy networking support. You can write servers or clients for many
popular internet protocols with just a few lines of code. Simple TCP
sockets are also easy.
* Python is an open source project with a permissive license.
* Superb community support. You can ask a question here and get a
response in minutes. :) You're not going to be left hanging when you
have a problem.
* With very VERY few exceptions, your code will run flawlessly on any
of the many platforms Python supports.

Python does have some issues, though; you'll either appreciate the
syntax or absolutely hate it, and there's no efficient and reliable
way to change/reload code in a running application (not often an
issue).

I'm sure others will add to this list, and there's at least one entry
that someone's likely to disagree with me on, but there's a start!

ChrisA
 
T

Tim Chase

So, assuming you'll say me "learn python", why should I learn it
over Ruby?

For me, most of Chris's answers apply to both Python and Ruby.
Well, I can't speak regarding the Ruby community being as awesome,
but it doesn't seem to scare off folks.

*READABILITY* is my main reason for choosing Python, particularly
over Ruby. I can come back to Python code I wrote 5+ years ago, and
it takes me mere minutes to reorient myself to the code. I can't do
that with most other languages, where it often takes me hours or
days to unwind the code.

-tkc
 
R

Roy Smith

Chris Angelico said:
there's no efficient and reliable way to change/reload code in a
running application (not often an issue).

What we do (largely cribbed from django's runserver) is start up a
thread which once a second, looks at all the modules in sys.modules,
checks to see if the modification time for their source files has
changed, and if so, restarts the application. This is hugely convenient
when developing any kind of long-running application. You don't need to
keep restarting the application; just edit the source and changes take
effect (almost) immediately.

Not sure if this is what you had in mind.
 
C

Chris Angelico

What we do (largely cribbed from django's runserver) is start up a
thread which once a second, looks at all the modules in sys.modules,
checks to see if the modification time for their source files has
changed, and if so, restarts the application. This is hugely convenient
when developing any kind of long-running application. You don't need to
keep restarting the application; just edit the source and changes take
effect (almost) immediately.

Not sure if this is what you had in mind.

It's not an _explicit_ restart, but you have to write your application
to keep all its state on disk in some way. What I'm talking about is
having a single process that never terminates, never stops accepting
connections, but at some point new connections begin to be served with
new code - with old ones, if they're still going, continuing to be
handled by the old code. I have one such process that's been going for
(let me check) 115 wk 0d 21:05:21.

For many types of application, restarting is perfectly viable, so this
isn't a major issue with Python.

ChrisA
 
R

Roy Smith

Chris Angelico said:
It's not an _explicit_ restart, but you have to write your application
to keep all its state on disk in some way.

Well, more strictly, what you need is to keep your state somewhere else.
Doesn't have to be on disk. Could be in memory, if that memory belongs
to another process (memcache, redis, or any of a number of in-memory
databases).
What I'm talking about is
having a single process that never terminates, never stops accepting
connections, but at some point new connections begin to be served with
new code - with old ones, if they're still going, continuing to be
handled by the old code. I have one such process that's been going for
(let me check) 115 wk 0d 21:05:21.

Why does it have to be a single process? I could imagine some front-end
process which accepts connections and hands them off to worker
processes. When you install new code, you could do it in a different
directory tree, and then signal the front end that new code exists. The
front end could then {chdir, munge sys.path, whatever} to the root of
the new tree and keep going. Existing connections stay up with the old
code, new connections get the new code.

If you didn't want to fork a new process every time, you could have a
worker process pool. When a worker signaled it was done with a task,
the front end could either assign it a new connection (if the code it
was running was still current), or kill it off if it was running stale
code.

If you truly needed this to be a single process, I could imagine a
customized module importer which altered the module name to include a
version prefix before registering it in sys.modules. I think that could
be made to work, but would be really ugly and complicated. Or elegant
and nifty, depending on your attitude :)
 
R

rusi

Hi!
I'm really new to Usenet/Newsgroups, but... I'd like to learn some new programming language, because I learnt a bit of Perl though its OOP is ugly. So, after searching a bit, I found Python and Ruby, and both of they are cute.
So, assuming you'll say me "learn python", why should I learn it over Ruby?
Thanks!
PS: I don't want to start a flame-war, I just want an advice if it's possible please!

Here's a test to help you decide: How do you respond to the word
'magic'?
If positive you will like Ruby, if not you may prefer Python.

Personal note: I like magic -- as long as its not in a tech area, eg
I'm a fan of Harry Potter.
 
C

Chris Angelico

Well, more strictly, what you need is to keep your state somewhere else.
Doesn't have to be on disk. Could be in memory, if that memory belongs
to another process (memcache, redis, or any of a number of in-memory
databases).

Sure. I'll generalize my statement to "Has to be external to the
process". That generally precludes the direct use of complex objects,
requiring some form of serialization or dump format - you can't, for
instance, retain a "socket connection object" across that sort of
reload.
Why does it have to be a single process? I could imagine some front-end
process which accepts connections and hands them off to worker
processes. When you install new code, you could do it in a different
directory tree, and then signal the front end that new code exists. The
front end could then {chdir, munge sys.path, whatever} to the root of
the new tree and keep going. Existing connections stay up with the old
code, new connections get the new code.

That's also a good model, for situations that can use it. My situation
is a MUD-like system where different clients can affect one another,
so the most logical way to do it is a single process. For instance, we
have a Dungeons and Dragons battle grid that uses a web browser as its
display engine; you go to a particular URL, key in your login details,
and it sends AJAX long polls to the server. Whenever one client moves
a token on the grid, every other client gets notified. I could, of
course, do this across processes, but I'd end up needing a hefty IPC
system; this way, all I need is a lightweight event semaphore that the
threads wait on, and they look at the process's internal structures
(thread-safe, they need only read at that point). I could have done it
in other ways, of course, but this is nice and straightforward.

But this is getting rather off-topic :) For the bulk of usage
patterns, Python's fine. Most languages don't let you reload code on
the fly, and most applications are never going to be bothered by this
miniscule feature lack!

ChrisA
 
M

Mark Lawrence

Hi!
I'm really new to Usenet/Newsgroups, but... I'd like to learn some new programming language, because I learnt a bit of Perl though its OOP is ugly. So, after searching a bit, I found Python and Ruby, and both of they are cute.
So, assuming you'll say me "learn python", why should I learn it over Ruby?
Thanks!
PS: I don't want to start a flame-war, I just want an advice if it's possible please!

http://www.gossamer-threads.com/lists/python/python/129650?do=post_view_threaded
 
R

Roy Smith

Chris Angelico said:
you can't, for instance, retain a "socket connection object" across
that sort of reload.

Yeah, that's a problem. There's nothing fundamental about a TCP
connection endpoint which precludes it being serialized and passed
around. The amount of state involved is pretty small. Unless I've
forgotten something, 2 IP addresses, 2 port numbers, a few bits worth of
TCP protocol state, and, for open connections, 2 sequence numbers.
Maybe a couple of timers, but I don't think they're strictly necessary.
The problem is, most of that state is private to the kernel.

On the other hand, you could do what "screen" does, and spawn a process
per connection to hold the connection open :)
 
C

Chris Angelico

Yeah, that's a problem. There's nothing fundamental about a TCP
connection endpoint which precludes it being serialized and passed
around. The amount of state involved is pretty small. Unless I've
forgotten something, 2 IP addresses, 2 port numbers, a few bits worth of
TCP protocol state, and, for open connections, 2 sequence numbers.
Maybe a couple of timers, but I don't think they're strictly necessary.
The problem is, most of that state is private to the kernel.

And can change at a moment's notice, with no userspace interaction.
The socket connection also needs to retain sent-but-not-acknowledged
and received-but-not-in-order data, so those buffers need to exist.
The only way would be for the kernel to export something representing
a socket - which would be the file handle.

And then you have to worry about any other state, eg if you're reading
line by line and are retaining a partial line... not really something
that can be patched in five seconds, and not IMHO worth trying to do.
Easier to simply retain the process ID.

Oh, and if the pid changes on a live connection, what will that do
with iptables controls, which can look at the originating process's
user id and such? Hrm.

ChrisA
 
S

Steven D'Aprano

Some might say that magic underscores a lot of the really fun stuff in
Python. See http://www.rafekettler.com/magicmethods.html

And they would be wrong.

The word they want is "special", not magic. There's nothing[1] magic
about double leading-and-trailing underscore methods. They are just
ordinary methods that are treated specially by Python to implement syntax
such as + (the __add__ and __radd__ methods), len() (the __len__ method)
and similar.

The article you link to starts off with this:

What are magic methods? They're everything in object-oriented
Python. They're special methods that you can define to add
"magic" to your classes.
[end quote]

Being able to add two values, or get the number of items in a container,
is hardly magic. They're *special*, because the compiler looks for
methods of those names, but that's all.

They're also not as well documented as they need to be. All of
the magic methods for Python appear in the same section in the
Python docs, but they're scattered about and only loosely organized.
[end quote]

You got that? They're all in the same section, AND they are scattered
about at the same time! Now that's truly magic! *wink*

Special is not magic. Magic means that the normal behaviour of the
language is broken for some arbitrary cases. Here's an example in
hardware of "magic":

http://catb.org/jargon/html/magic-story.html

Now imagine that in software: it can't possibly work, and yet it does.

I dare say nearly all non-toy languages have *some* magic. But some
languages have more than others: they are full of unique cases, every one
different, where the same code behaves differently that you would expect.
There *is* some magic in Python:

* Methods and attributes that start with a double underscore, but do not
end with a double underscore, have their name mangled by the compiler.
So your source code says "MyClass.__method", but the method actually
created is "MyClass.__MyClass_method".

This is magic because __names everywhere else do not work that way,
nor do names that don't start with double-underscores.

* In Python 3, if you call super() with no arguments inside a class,
the compiler runs some voodoo to determine the class it belongs to
and the instance it is called from. Outside of a class, super()
with no arguments behaves like any other function.

This is magic because the normal behaviour of a function with two
required arguments is to fail if you don't provide the arguments.
But super() can, somehow, determine the arguments itself, partially
at compile-time and partially at run-time.

* The relationship between built-ins type() and object() is magic.
object is a type. But type is itself an object. You can't define
object until type exists, and you can't define type until object
exists. But the compiler magically bootstraps them into existence.

This is magic because it is impossible[2] for pure Python code to
bootstrap such mutually-defined types into existence.

Off the top of my head, I can't really think of anything else that is
magic in Python.

Note that individual uses of magic are generally done for good reasons,
or at least what seems like a good reason. For example, super's magic
class detection is useful and prevents bugs. But *in general* magic is a
bad thing, because it makes the language incomprehensible and code
surprising. Languages with a lot of magic tend towards code which is hard
to maintain and debug.

Note also that "magic" is different from "deep magic" and "black magic":

http://catb.org/jargon/html/M/magic.html




[1] Perhaps not quite *nothing*, arguably there is a *tiny* bit of magic
in that Python bypasses the instance when looking up __dunder__ methods
as a speed optimization. But that's more like a sprinkle of fairy dust
than real magic.

[2] Or at least tricky and messy.
 
H

Hans Mulder

Yeah, that's a problem. There's nothing fundamental about a TCP
connection endpoint which precludes it being serialized and passed
around. The amount of state involved is pretty small. Unless I've
forgotten something, 2 IP addresses, 2 port numbers, a few bits worth of
TCP protocol state, and, for open connections, 2 sequence numbers.
Maybe a couple of timers, but I don't think they're strictly necessary.
The problem is, most of that state is private to the kernel.

You're looking at the wrong abstraction level. A socket connection
object is a thin wrapper around a file descriptor. Most posix platforms
allow you to pass file descriptors to other processes running on the
same box. Thus, most posix platforms *do* allow you to pass socket
connection objects around, though you won't win prizes for portability.
On the other hand, you could do what "screen" does, and spawn a process
per connection to hold the connection open :)

That won't work for the sort of application we're discussing, because
it creates too many processes. A pool of processes, each handling
many connections, might work though.

-- HansM
 
C

Chris Rebert

The point why Ruby was started (perceived deficit of object-orientation)
has been remedied since Python 2.2.

Not completely. At the least, there's arguably still the issue of
len() and friends (vs. `.length` etc.), and also of `self` being
explicit.

Cheers,
Chris
 
S

Steven D'Aprano

Not completely. At the least, there's arguably still the issue of len()
and friends (vs. `.length` etc.), and also of `self` being explicit.

I'm not entirely sure which "perceived deficit of object-orientation" is
being talked about, or why anyone but OOP purists would consider that a
problem.

Python is *more* object-oriented than Java, and I don't hear anyone
complaining that Java isn't object-oriented. Everything[1] in Python is
an object. *Everything*. Ints are objects. Strings are objects. Arrays
are objects. There's no distinction between "boxed" and "unboxed" ints,
like in Java or Haskell -- Python just has ints, and they're always
objects.

As for len() and friends, that's a red-herring. Just because the syntax
is written len(x) instead of x.len() doesn't make Python less object-
oriented. It's just syntax: "a + b" is no less OO than "a.plus(b)".

Somebody might not *like* the syntax "a + b", or "len(x)", but they
should just say so, and not pretend that it isn't OO.

Likewise self. Explicit or implicit, how does that make a language less
or more object-oriented? That's as foolish as saying that Python isn't
object-oriented because you don't have to declare the type of variables:

x = (float)1.234

Again, there are arguments for and against explicit self, but "explicit
self is not OO" is not a valid argument.

Being object-oriented has both costs and benefits. Java compromises on
the idea of OOP for performance: native, non-object ints are faster than
object ints. All these people complaining that Python isn't OO enough
because you have to write "self" in method declarations, why aren't they
complaining that Java isn't OO enough because ints are unboxed primitive
types?



[1] Emphasis on the *thing* part. Control structures aren't things in
that sense, they aren't values at all, they are actions that takes place
during execution.
 
W

Wolfgang Keller

The point why Ruby was started (perceived deficit of
I'm not entirely sure which "perceived deficit of object-orientation"
is being talked about, or why anyone but OOP purists would consider
that a problem.

Yukihiro Matsumoto did. I myself never perceived any lack of
object-orientation with Python, since I've learned programming with
Pascal anyway. >;->

I just wanted to point out that given the state of Python today, no one
would probably consider starting Ruby any more.

Sincerely,

Wolfgang
 

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,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top