4 ms·
Hmmm, I don't think this article accurately represents how people write python since ~2005. I'm biased because I use python every day, but there's a big objecti
by mgraczyk 5y ago
Hmmm, I don't think this article accurately represents how people write python since ~2005. I'm biased because I use python every day, but there's a big objective mistake.
> Ruby flips the script, giving the objects deeper customizability.
Not really, because python allows you to do things the Ruby way, but I'm not sure the reverse is true.
class Stuff:
def __init__(self):
self.a = [1, 2, 3, 4]
def __iter__(self):
for item in self.a:
yield item
and you can write it more simply in this case.
def Stuff():
a = [1, 2, 3, 4]
for item in a:
yield item
What about the select and map example?
class Stuff:
def __init__(self):
self.a = [1, 2, 3, 4]
def __iter__(self):
for item in self.a:
yield item
def map(self, f):
for item in self.a:
yield f(item)
Which can be used just like the ruby example, with syntax of similar ugliness.
print(Stuff().map(lambda item: item))
I think I could come up with a python example that maps 1:1 onto pretty much any ruby example, but I don't think it's possible in general to find ruby examples that map onto more complicated python.
- softwaredoug 5y agoAuthor here! Very true, though I was trying to focus on idiomatic python that pushes logic into for loops, list comprehensions, etc w/ composable iterators through tools like those found in itertools (zip, etc...) Since Python doesn't have Ruby's blocks, you have to define a non-trivial function as a free function, so it's less likely you'll do this. (Python's lambda's are far more limited than Ruby's blocks.) You can also trick Ruby to return a new value every time a method is called for iteration, but again my focus on what I see as idiomatic in the two languages
- gvx 5y agoYour Python example is far from idiomatic, though. If a Python programmer were forced to write `Stuff`, they'd write something like: class Stuff: def __init__(self): self.a_list = [1,2,3,4] def __iter__(self): return iter(self.a_list) --- or do what the other person did, and make `__iter__` a generator, which isn't necessary in this case but is much more flexible.
- softwaredoug 5y agoYes, but if you’re new to Python you’re not going to grok this.
- zedr 5y ago> think I could come up with a python example that maps 1:1 My take on it: class Stuff: def __init__(self): self._list = [1, 2, 3, 4] @property def each(self): for el in self._list: yield el for item in Stuff().each: print(item) It's even less verbose than the Ruby equivalent in the original article, thanks to the indentation-defined blocks.
- teddyh 5y agoAFAIK, there is no reason to use the form “for el in self._list: yield el”, unless you are running Python 3.2 or older. Why not: each = self._list Or, if you need to be able to re-assign self._list to a new object: @property def each(self): return self._list Or, if you for some reason need it to return an iterator: @property def each(self): return iter(self._list) Or, if you really want it to be a generator function: @property def each(self): yield from self._list