3 ms·
Thank you. Why is 3 stupid? That would be my preference. It is clear, simple and gets compiled away (in many cases). I alias in variables frequently, to make t
by sago 11y ago
Thank you.
Why is 3 stupid? That would be my preference. It is clear, simple and gets compiled away (in many cases). I alias in variables frequently, to make things more explicit. For example, I might write
iterations = 300
for _ in range(iterations):
...
which makes it less likely I'll end up repeating things or copy and pasting when new cases come up, e.g.
if not shipment_qty:
abort(400, message)
elif shipment_qty < 0:
abort(400, message)
What happens in your case if you come back and edit the message and add a few characters, exceeding your longer line length?
When I'm forced to break a string it is usually an indication that I need a better way of defining text than inline in expressions in code.
- pyre 11y ago> Why is 3 stupid? Just to be clear, I do use that pattern in practice, but I usually feel 'dirty' about it. Sometimes I also do things like this: is_admin = (membership.type == 'master') is_current_group = (membership.group == session.group) if is_admin or is_current_group: do_something() but I find this easier to justify because I'm adding something more than just the breakup of a line. I'm adding semantic meaning to other developers reading the code. In the example I gave, saying "message=msg" doesn't add anything (as opposed to say "message=bad_shipment_msg", but maybe the definition of "bad_shipment_msg" pushes the string past 80 columns by itself). As for the example of reusing the message, maybe it's bad practice, but I would end up with tailored messages describing the edge case (e.g.): if not shipment_qty: abort(400, message='Must pass a quantity') elif shipment_qty < 0: abort(400, message='Quantity must be > 0') Edit: I do the boolean definition thing more then "sometimes" because I prefer to make complex boolean operations easy to understand, and to also convey the meaning of what you want to achieve.
- sago 11y agoI think it is pretty essential for boolean expressions too, yes, anything that isn't a single comparison, at least. Interesting you find aliasing in variables 'dirty'. Would you feel dirty writing something like def my_method(self): contents = self.contents ... etc ... which I use often if I'm going to use self.contents a lot in that method. It has some performance benefit in rare cases, but mostly it reduces clutter, makes lines smaller, and means I type less. But again, it is 'pointless', in one sense. From the current code open on my machine, even one character variable names!: w, h = self.width, self.height ... Dirty? Stupid? (I'm not being facetious, I'm genuinely interested in your aesthetic sense here).
- coldtea 11y agoWith autocomplete you don't get anything with "one character var names" (leave those for i, j, k etc). And no reason to pollute the local namespace with both self.contents and contents. What if you do this somewhere lower for example: contents = contents[:limit] did you mean to NOT change self.contents? Because that's what you got. Whereas: self.contents = self.contents[:limit] would propagate it.
- sago 11y ago> (leave those for i, j, k etc) Why use them then if you have autocomplete? Since character variable names are useful as very short conventions, I'd never want to see them used generally. Someone working in this code would have to know the meaning immediately from the name, as for any variable. In my application area x,y,w,h,r (radius) and c (context - which is domain specific, but is present in about 50% of LOC in my current code-base) are all as ubiquitous as i and j (I'd probably not be comfortable with k, too deep nesting). i and j are much rarer in python, either using sequences of underscore for 'don't care'. On the second point, there is reason, as I pointed out. It makes code shorter, clearer, and in some cases more performant (when contents is a property, for example). Don't get me wrong, I was following up on the specific point, I wasn't trying to recommend this style as good general practice (alias all your self variables at the top of a method - erm, no). The lack of 'const'ing in python is a risk, yes. We use immutable data structures whenever possible, including immutable classes, because we try to ensure as much code is written without side effects on data. I'd want to not alias variables that have side effects applied to them, yes. But you're right that it makes it easier for a sloppy edit to mess things up. In most cases the 'sloppy' would be adding the side effects at all, however, which either version has. Still, in pages of such code, it helps to write cos_t = math.cos(theta) sin_t = math.sin(theta) x, y = self.position.x, self.position.y return x*cos_t - y*sin_t, x*sin_t + y*cos_t rather than cos_theta = math.cos(theta) sin_theta = math.sin(theta) return self.position.x * cos_theta - self.position.y * sin_theta, self.position.x * sin_theta + self.position.y * cos_theta particularly as the number of uses of x and y increase beyond two in a functon. Ultimately code-quality and maintainability can't be mandated by a PEP or any universal rule. But like any field, you have to understand the purpose of the rule, and weigh up its risks and benefits before you break it.
- BurningFrog 11y agoI think 3 is bad because it is more complex than the natural code. It's not incomprehensible, of course, but clearly more complex. I like introducing named variables for readability a lot. But this doesn't help readability. It just adds complexity for the sake of fitting into 80 characters.
- sago 11y ago> But this doesn't help readability. It just adds complexity for the sake of fitting into 80 characters. But 'for the sake of' implies that it has no other purpose. But the purpose is readability. It will help readability for the vast population of programmers who have 80 col editors or shells, and who code according to PEP8, won't it? Isn't that the point? Of course you can say 'It would be more readable if you guessed my window width preference correctly'. But what should I guess? If I look at your code and see a 90 col line somewhere, how do I know you won't drop a 100 col line in and hurt the readability again? Do I have to read your README to find how big to make my windows? Or do I just take the readability hit for the sake of your preference?
- Chris_Newton 11y agoIt will help readability for the vast population of programmers who have 80 col editors or shells Isn’t that the premise that is being challenged here, though? There’s plenty of variety in which editors and shells experienced programmers prefer to use, but do any of those tools really still have a hard 80 column limit in 2015? I would guess most developers now use screens that can show at least two (and often three or even four) source files side by side and still cope with longer lines than that, and I would guess most could switch their editor or shell to cope with those wider lines in a fraction of a second with a single keyboard shortcut. I can see cases where line length could still be a limiting factor, but I’m not sure giving up general readability improvements from allowing somewhat longer lines so it’s easier to do a three-way merge on a laptop with a smaller screen is a good trade.
- sago 11y agoNobody is suggesting that people Can't view more than 80 cols. But many people have their machines and environments set up for 80 cols. They have their windows laid out based on the code they're writing, and then they load a new file and have to drag and resize their environment to accommodate you. If there's a way to change window size and position from 3 columns of 80 + a project browser into 120 col with a single keypress, then I'd like to know. It isn't a major problem, but it is an unnecessary problem. Nobody is forced to use long lines either, and if you want to lay out your environment to support 120 cols and you get my 80 col source code it will work without even a keypress or a second thought. You won't even notice it.
- zo1 11y agoHave you thought about: message = "Shipment seems fine" if not_shipment_qty: message = "Shipment is not fine" elif shipment_qty < 0: message = "No quantity" abort(400, message)
- pyre 11y agoThat is semantically different. It always calls abort(). In this case abort() raises an exception that returns a HTTP 400. I'm not going to abort if everything seems fine. :P If you wanted to do this pattern, it would look more like this: message = None if not_shipment_qty: message = "Shipment is not fine" elif shipment_qty < 0: message = "No quantity" if message: abort(400, message=message) (Note: In this case the keyword argument form of message is required, because all keyword args get packaged up into a JSON body of the response.)