Which abbreviations should we use for python variable names? - python

In generally I'm using the standard naming stated in PEP-8 for variables. Like:
delete_projects
connect_server
However sometimes I can't find any good name and the name just extend to a long one:
project_name_to_be_deleted
I could use pr_nm_del , but this makes the code unreadable. I'm really suffering finding good variable names for functions. Whenever I begin to write a new function I just spent time to find a good variable name.
Is there any standard for choosing certain abbreviations for well known variable names like, delete,project,configuration, etc. ? How do you choose short but good and readable variable names ?
This question might be not depend directly to Python, but as different programming languages uses different variable names formatting I thought I limit this question to Python only.

pr_nm_del? You might as well let a cat name it. I believe abbreviations should be avoided at all cost, except well-known/obvious ones (like del, as mentioned in the comments - that one's even a language keyword!) that save a whole lot of typing.
But that doesn't mean overly verbose identifiers. Just as context is important to understand statements in natural languages, identifiers can often be kept much shorter (and just as understandable) by referring to context. In your example, project_name is perfectly fine - the procedure is already called delete_project, so project_name obviously refers to the name of the project to be deleted. Even name alone might be fine. No need to state that again by appending _to_be_deleted.

In your example, you have a function called delete_project. Wondering what to call the variable that stores the project to be deleted? Just 'project'!
def delete_project(self, project):
del self.projects[project]
Simple.
Variable names don't have to be fully descriptive. Context can lend a lot to how we understand a particular name at a particular point in time. No need to say "this is the project to be deleted" when discussing a function that deletes project.
If you find function names are too long, they're probably doing too much. If you find variable names are becoming too long, think about their purpose in the current context, and see if part of the name can be implied.

This is a problem that kind of solves itself when you're doing OOP. The subject (project, configuration) is the class and the verb (delete, etc) is the method name ie:
class Workspace(object):
def delete_project(self, project):
log.info("Deleting", project.name)
...

I think long names are acceptable provided that they are descriptive. With a good editor/IDE, short names cannot save typing, while long but descriptive names can save the time of reading your code. So the length of the reading time of the name is much more important than the actual length of the name.
As for your example, project_name_to_be_deleted is fine. If you want to shorten it, I will suggest using project_name_to_del since del is a well-known abbreviation for delete (you can even find this in your keyboard). And the use conf as configuration is also popular. But don't go further. For example, proj2del is not a good idea.
Also, for internal/local things, it's fine to use short-not-so-descriptive names.

Very few names have "standard" abbreviations. What you think is "common" or "standard" is not the same for someone else.
The time spent setting a good name is well invested, as code is read much more often than it is written.
As an example, I've seen
"configuration"
abbreviated as
"config"
"cnfg"
"cfg"
"cnf"
...so the lesson is - don't abbreviate unless there is a very well known abbreviation of it!

Related

Is it a good idea to dynamically create variables?

I recently found out how to dynamically create variables in python through this method:
vars()['my_variable'] = 'Some Value'
Thus creating the variable my_variable.
My question is, is this a good idea? Or should I always declare the variables ahead of time?
I think it's preferable to use a dictionnary if it's possible:
vars_dict = {}
vars_dict["my_variable"] = 'Some Value'
vars_dict["my_variable2"] = 'Some Value'
I think it's more pythonic.
This is a bad idea, since it gets much harder to analyze the code, both for a human being looking at the source, and for tools like pylint or pychecker. You'll be a lot more likely to introduce bugs if you use tricks like that. If you think you need that feature at some time, think really hard if you can solve your problem in a simpler and more conventional way. I've used Python for almost 20 years, and never felt a need to do that.
If you have more dynamic needs, just use a normal dictionary, or possibly something like json.
One of the great things with Python, its dynamic nature and good standard collection types, is that you can avoid putting logic in text strings. Both the Python interpreter, syntax highlighting in your IDE, intellisense and code analysis tools look at your source code, provides helpful suggestions and finds bugs and weaknesses. This doesn't work if your data structure or logic has been hidden in text strings.
More stupid and rigid languages, such as C++ and Java, often makes developers resort to string based data structures such as XML or json, since they don't have convenient collections like Python lists or dicts. This means that you hide business logic from the compiler and other safety checks built into the language or tools, and have to do a lot of checks that your development tools would otherwise do for you. In Python you don't have to do that ... so don't!
There is no guarantee that vars()['myvariable'] = 'Some value' and my variable = 'Some value' have the same effect. From the documentation:
Without an argument, vars() acts like locals(). Note, the locals
dictionary is only useful for reads since updates to the locals
dictionary are ignored.
This code is simply wrong.
Pros:
adds another level of indirection, makes the environment more dynamic
in particular, allows to avoid more code duplication
Cons:
not applicable for function namespaces (due to optimization)
adds another level of indirection, makes the environment more dynamic
"lexical references" are much harder to track and maintain
if created names are arbitrary, conflicts are waiting to happen
it's hard to find the ins and outs in the code base and predict its behaviour
that's why these tricks may upset code checking tools like pylint
if variables are processed in a similar way, they probably belong together separately from others (in a dedicated dict) rather than reusing a namespace dict, making it a mess in the process
In brief, at the abstraction level Python's language and runtime features are designed for, it's only good in small, well-defined amounts.
I don't see what would be the advantage of it, also would make your code harder to understand.
So no I don't think it is a good idea.

Naming conventions for function arguments in python

Should the names of function arguments reflect the context of the function in which they are used?
To give a concrete example in Python, (taken from this textbook):
def create_radio_button(rb_name, rb_value):
vs
def create_radio_button(name, value):
The Python style guide suggests using underscores to avoid keyword clashes, but doesn't mention the use of prefixes in arguments. In Clean Code, Bob Martin suggests choosing variable names that are pronounceable and to avoid encodings, which perhaps counts against an rb_ prefix. However, he follows this by stating that variable names should be searchable. My primary goal is to improve the clarity of my code, so I'm interested to hear what people have found easiest to work with.
It depends on context, and perhaps on personal preference to some extent.
def create_radio_button(name, value)
Recommend the above over the other option here, because I can see from the context that we are talking about a radio button so the "rb_" prefix is redundant information, it is already duplicated in the function name.
The comment about variable names being searchable I guess refers to the poor practice of using a variable name such as p, where you might want to search or highlight the variable name, resulting in the annoyance of finding any word containing a p. This issue doesn't apply so much here, "name" and "value" would be searchable enough*.
* This last point is somewhat moot for people using a decent editor, where we can refactor/rename a symbol and the IDE should be smart enough to know where the usages are in context/scope
This is a more general question than just python. The parameter name should describe its role as concisely as possible (so I would just use "name" and "value" in your example).
Of course, this doesn't replace actual documentation, for which I would recommend the somewhat standard tags
:param name: description
:param value: description
(you can also add the expected type of the parameter before its name in the above)
In general, the function should be relatively short, so it is fairly obvious that 'name' is a parameter to the function.
I think using the rb_ prefix would only make sense for global variables, which, in a python application, should be pretty rare (better use class variables).

How do I name a variable with acronym?

For example in Java for Data Transfer Object I use as:
ExampleDTO exampleDTO = new ExampleDTO();
So, if I am following PEP 8 (lower_case_with_underscores), what naming convention should I use for similar in Python?
The style most agreeing with PEP-8 would probably be...
example_dto = ExampleDTO()
You may want to look at Python Style Guide
I personally use camelCase for variables and _ (underscore) separated in method names.
Why use acronyms in the first place? I try to avoid them when possible. They obfuscate the code and tend to create code that is hard to browse for quick read. Worst case they bring bugs because of misinterpretation (RndCmp was a Random Compare not a Rounded Complex).
What is DTO? Will it still be used in 2 years? Will every new guy immediately know what it means? In 5 years from now too? Can it be confused with anything else? (Deterministic and Transferable Object?)
The only true (and honest) reason for using acronyms is pure coder laziness. My fun in meetings is to ask about acronyms in variable names and 80% of the times nobody really knows. Even the old guys forget what it meant a couple of years back. We even have some with more than one meanings.
With today great IDE (??) with auto-complete of variable names, laziness is a very bad reason to keep them around. By experience you cannot prevent them, but they should always be questioned.

Code organization in Python: Where is a good place to put obscure methods?

I have a class called Path for which there are defined about 10 methods, in a dedicated module Path.py. Recently I had a need to write 5 more methods for Path, however these new methods are quite obscure and technical and 90% of the time they are irrelevant.
Where would be a good place to put them so their context is clear? Of course I can just put them with the class definition, but I don't like that because I like to keep the important things separate from the obscure things.
Currently I have these methods as functions that are defined in a separate module, just to keep things separate, but it would be better to have them as bound methods. (Currently they take the Path instance as an explicit parameter.)
Does anyone have a suggestion?
If the method is relevant to the Path - no matter how obscure - I think it should reside within the class itself.
If you have multiple places where you have path-related functionality, it leads to problems. For example, if you want to check if some functionality already exists, how will a new programmer know to check the other, less obvious places?
I think a good practice might be to order functions by importance. As you may have heard, some suggest putting public members of classes first, and private/protected ones after. You could consider putting the common methods in your class higher than the obscure ones.
If you're keen to put those methods in a different source file at any cost, AND keen to have them at methods at any cost, you can achieve both goals by using the different source file to define a mixin class and having your Path class import that method and multiply-inherit from that mixin. So, technically, it's quite feasible.
However, I would not recommend this course of action: it's worth using "the big guns" (such as multiple inheritance) only to serve important goals (such as reuse and removing repetition), and separating methods out in this way is not really a particularly crucial goal.
If those "obscure methods" played no role you would not be implementing them, so they must have SOME importance, after all; so I'd just clarify in docstrings and comments what they're for, maybe explicitly mention that they're rarely needed, and leave it at that.
I would just prepend the names with an underscore _, to show that the reader shouldn't bother about them.
It's conventionally the same thing as private members in other languages.
Put them in the Path class, and document that they are "obscure" either with comments or docstrings. Separate them at the end if you like.
Oh wait, I thought of something -- I can just define them in the Path.py module, where every obscure method will be a one-liner that will call the function from the separate module that currently exists. With this compromise, the obscure methods will comprise of maybe 10 lines in the end of the file instead of 50% of its bulk.
I suggest making them accessible from a property of the Path class called something like "Utilties". For example: Path.Utilities.RazzleDazzle. This will help with auto-completion tools and general maintenance.

Is late binding consistent with the philosophy of "readibility counts"?

I am sorry all - I am not here to blame Python. This is just a reflection on whether what I believe is right. Being a Python devotee for two years, I have been writing only small apps and singing Python's praises wherever I go. I recently had the chance to read Django's code, and have started wondering if Python really follows its "readability counts" philosophy. For example,
class A:
a = 10
b = "Madhu"
def somemethod(self, arg1):
self.c = 20.22
d = "some local variable"
# do something
....
...
def somemethod2 (self, arg2):
self.c = "Changed the variable"
# do something 2
...
It's difficult to track the flow of code in situations where the instance variables are created upon use (i.e. self.c in the above snippet). It's not possible to see which instance variables are defined when reading a substantial amount of code written in this manner. It becomes very frustrating even when reading a class with just 6-8 methods and not more than 100-150 lines of code.
I am interested in knowing if my reading of this code is skewed by C++/Java style, since most other languages follow the same approach as them. Is there a Pythonic way of reading this code more fluently? What made Python developers adopt this strategy keeping "readability counts" in mind?
The code fragment you present is fairly atypical (which might also because you probably made it up):
you wouldn't normally have an instance variable (self.c) that is a floating point number at some point, and a string at a different point. It should be either a number or a string all the time.
you normally don't bring instance variables into life in an arbitrary method. Instead, you typically have a constructor (__init__) that initializes all variables.
you typically don't have instance variables named a, b, c. Instead, they have some speaking names.
With these fixed, your example would be much more readable.
A sufficiently talented miscreant can write unreadable code in any language. Python attempts to impose some rules on structure and naming to nudge coders in the right direction, but there's no way to force such a thing.
For what it's worth, I try to limit the scope of local variables to the area where they're used in every language that i use - for me, not having to maintain a huge mental dictionary makes re-familiarizing myself with a bit of code much, much easier.
I agree that what you have seen can be confusing and ought to be accompanied by documentation. But confusing things can happen in any language.
In your own code, you should apply whatever conventions make things easiest for you to maintain the code. With respect to this particular issue, there are a number of possible things that can help.
Using something like Epydoc, you can specify all the instance variables a class will have. Be scrupulous about documenting your code, and be equally scrupulous about ensuring that your code and your documentation remain in sync.
Adopt coding conventions that encourage the kind of code you find easiest to maintain. There's nothing better than setting a good example.
Keep your classes and functions small and well-defined. If they get too big, break them up. It's easier to figure out what's going on that way.
If you really want to insist that instance variables be declared before referenced, there are some metaclass tricks you can use. e.g., You can create a common base class that, using metaclass logic, enforces the convention that only variables that are declared when the subclass is declared can later be set.
This problem is easily solved by specifying coding standards such as declaring all instance variables in the init method of your object. This isn't really a problem with python as much as the programmer.
If what the code is doing becomes mysterious for some reason .. there should either be comments or the function names should make it obvious.
This is just my opinion though.
I personally think not having to declare variables is one of the dangerous things in Python, especially when doing classes. It is all too easy to accidentally create a variable by simple mistyping and then boggle at the code at length, unable to find the mistake.
Adding a property just before you need it will prevent you from using it before it's got a value. Personally, I always find classes hard to follow just from reading source - I read the documentation and find out what it's supposed to do, and then it usually makes sense when I read the source again.
The fact that such stuff is allowed is only useful in rare times for prototyping; while Javascript tends to allow anything and maybe such an example could be considered normal (I don't really know), in Python this is mostly a negative byproduct of omission of type declaration, which can help speeding up development - if you at some point change your mind on the type of a variable, fixing type declarations can take more time than the fixes to actual code, in some cases, including the renaming of a type, but also cases where you use a different type with some similar methods and no superclass/subclass relationship.

Categories