Only one of the items in your "such as" list is unique to python's philosophy, and that is "there should be one way to do it". Ruby embraces the many ways to accomplish something, it's true. However, the three others are not unique to python. Ruby especially embraces "readability counts". And I can't think of anything in the ruby language itself that is implicit over explicit. Perhaps you are thinking of rails and comparing that to python.
For me, the Ruby community's comfort with monkey patching was a big turn off. In Python, you can hack around on class and replace its methods, but if you do, it's expected that your coworkers might stick you in a dunk tank and sell tickets. It's just not the thing that's done.
Monkeypatching is maybe more of a Rails thing than Ruby. I think the biggest problems with Ruby around the time Python began to take off were slowness (MRI was a disaster, slow, and full of memory leaks), plus patchy documentation (lots of things were in Japanese).
Still, I preferred and prefer Ruby. Python has fantastic libraries, but it is a mediocre language. Ruby feels like a simpler version of Perl + Smalltalk, and it is a joy to use. Python has intentionally crippled anonymous functions plus syntactic whitespace, which often leads to long and ugly code.
I think it is a shame Guido hated functional programming and he did not embrace an Algol-like syntax with begin/do end blocks. Those two things could have vastly improved Python. Ruby's block, procedure and lambda design is a stroke of genius that yields beautiful code and makes DSLs trivial.
For me, the Ruby community's comfort with monkey patching was a big turn off
If it helps, the Ruby community really soured on monkeypatching in general quite a while back. You don't see it much these days and every decent book or guide warns against it.
It was definitely a crazier place 10+ years ago in the early Rails days.
I certainly wouldn't blame a person for experiencing those crazier days and thinking the community didn't have the greatest technical vision.
I played around with Rails and Ruby when Rails first blew up. But I didn't start doing it fulltime professionally until 2014. By the time it seemed to me that the community was maturing. I think it's in a good place now.
An easy way to start taking the fight back to the enemy is by overriding __new__ and tinkering with things before/after Django's metaclass __new__ does its own metafoolery.
Also overriding mro() is a fun way to monkey with the inner workings.
> And I can't think of anything in the ruby language itself that is implicit over explicit
This is surprising to me. I love ruby, but it embraces implicitness more than any other language I've used. method_missing, monkey patching internals, and other types of metaprogramming make things very implicit at the interface level
Scala's implicits are a lot less unpleasant because the type system means that you (and, perhaps more importantly, your IDE) know exactly where they're happening.
Python has a default None return, Ruby returns the value of the last expression.
Neither (except maybe the None case in Python) is really implicit, Ruby is just an expression oriented language while Python is statement-oriented.
OTOH, in Ruby the keyword “return” is superfluous except for altering control flow for an early return, while in Python it is the mechanism for supplying a return value.
Doesn’t seem like that big of a deal. You’re going to have a really hard time getting your first test to pass if you make a mistake.
I don’t mean using testing as a poor man’s type system, I mean even the tests you would write in a statically typed language will quickly uncover any mistakes you could possibly make there.
> In statically typed systems, this wouldn't even compile.
Still, it's not like you're going to miss that a function doesn't return something expected. Even in statically typed languages you are going to have tests to validate that much.
> I'm pretty sure I'd see multiple cases where the function would return different types depending on a code path.
That's another problem entirely. Although even then it would be pretty hard for an errant type to not blow up your tests. Again, not tests specifically meant to check that your types or sane, just the same tests you would write in a statically typed language.