8

I'm confused about choosing names for my functions in Python. Sometimes Python built-in functions are imperative such as: print function and string method find. Sometimes they aren't such as: len its name isn't imperative such as calculate_len, for instance, and type isn't find_type.

I can understand that print returns a value that we don't use (i.e None) and does something (i.e it shows a string on the screen), so its name is imperative.

But len returns a value that we use and does something (i.e. calculating how many items there are in a sequence or a mapping.) and its name isn't imperative. On the other hand, find string method (as len) returns a value that we use and does something, and its name is imperative.

What made ask this question is that I put a script that encrypt and decrypt string using Caesar cipher to being reviewed. The reviewer said that:

Just a gut feeling: functions do stuff. So a good name for a function is an imperative: I'd use rotate_letter instead of rotated_letter.

rotated_letter returns a single-letter string representing a letter rotated by a number. I don't know what is better, I used rotated_letter as it returns a value, like randint function in random module, it isn't generate_randint.

So, in this case, how should I name a function that returns a value to be used? Should I make the name imperative or just a noun. In other cases it's obvious how to do it, such as boolean functions, such as is_even and is_palindrome we just make it like a yes/no question, and also functions that just do and return non-used values (i.e None), such as print and list method sort.

  • that's actually a very common practice (i would say a convention) to use imperatives when naming function. For instance how do you name a variable that stores the rotated letter of the function rotated_letter ? – JoulinRouge Oct 20 '16 at 13:20
  • That's not a good way of thinking of some of your examples. len, for example, is better thought of as "length of" - you're getting a meta-level description of its argument. – Izkata Oct 20 '16 at 13:23
7

Use verbs where reasonable, nouns if they are shorter and unambiguous

Most of the time, functions should be (imperative) verbs and classes, variables, and parameters should be nouns. Attributes should also be nouns, including those created using @property. This is especially the case for functions which have side effects.[1] If a function does return something, you should evaluate whether the verb adds something or is just "noise":

  • make_list(foo) vs. list(foo): The noun is easier to read than the verb. Also, list is actually a class, and classes should be nouns.
  • open(foo) vs. file(foo): The verb is easier to read than the noun, and it makes more sense to give "options" to a verb than to a noun, so the noun was removed in Python 3. open() remains the only "standard"[2] way to create file objects in Python 3.
  • foo.get_bar() vs. foo.bar() vs. foo.bar (assume foo and bar are both nouns): The first option is right out, because the "get" doesn't add anything that we didn't already know. The second is appropriate if getting a bar out of a foo is a potentially expensive operation and/or carries side effects (you might also consider Bar(foo) if Bar is a class). The third is appropriate if this is a cheap operation with no side effects, and alternative implementations are unlikely to make it expensive.
  • xs.sort() vs. sorted(xs) if xs is a list: The first is imperative: Sort the list. It modifies the list in-place and returns nothing. The second is declarative: A list that is sorted, which is precisely what it returns. Both are verbs.

[1]: Usually returning a value and having side effects are mutually exclusive unless you have some compelling design reason to combine them. So a function that has side effects should probably not return anything and hence making it a noun would make very little sense.
[2]: There are some moderately lower-level operations in the io module which can be used to add or remove file buffering, automatic text en/decoding, etc., and these are mostly nouns because they are object-oriented classes. Most users do not need to play with these things directly; instead, open() chooses an appropriate class and instantiates it automatically.

  • Thank you! In "foo.get_bar() vs.` foo.bar()` vs. foo.bar" what is the difference between the second and the third? – Mahmud Muhammad Naguib Oct 21 '16 at 15:22
  • The third is either a property or a bare attribute. The second is a method. – Kevin Oct 21 '16 at 15:22
  • So, if I understand, it's appropriate not to make rotated_letter imperative and keep it declarative, right? – Mahmud Muhammad Naguib Oct 21 '16 at 15:29
  • In this case I'm not sure whether letter is implied by context. – Kevin Oct 21 '16 at 15:33
-1

rotated_letter doesn't look like a method. It looks like a property. Which means that the first idea is to do:

var letter = caesar.rotated_letter

expecting letter to contain a value of type string, not a function. From there, either you chose a different name, such as:

def rotate_letter(self):
    pass

or you use a property instead:

@property
def rotated_letter(self):
    return self.whatever

len and type are named like that because any other name would be long to type. They are used a lot, and they have a special status of core Python functions that every Python programmer will learn anyway, making their names much more irrelevant than the names of third-party libraries.

len, especially, is a good example of what you shouldn't do in your code: you're expected to use full names such as length (unless the short form is very popular, such as max), and use a verb, such as compute_length. Or it could be a property: len([1, 5, 6]) becomes [1, 5, 6].length. For instance, in C#, the later form is used: new [] { ... }.Length.

Note that there may be historical reasons as well for len: other languages, such as C#, preferred Count, which is usually a method (although the behavior is unfortunately inconsistent through .NET Framework). Count is a verb, so intuitively, you're inclined to invoke it as a method.

Returning values or performing an action

A function is always expected to perform an action. If it barely returns a value, it should be a property. You have a hint that the function should be transformed into a property when:

  • The function barely contains a return ... statement,

  • The function's name which comes naturally into your mind is get_something, as in product.get_price().

Now, if you have a function, it can be one of four types:

  • It can be pure, that is return a value without affecting the environment. Example: road.measure_distance().

  • It can affect the environment without returning anything. Example: product_database.remove_record(1234).

  • It can affect the environment and return a value. Example: value.increment() used such as value++.

  • It can do nothing and return nothing. Example: time.sleep(1).

There are few cases where the name could give a strong hint about the type of the function, but in many cases, you won't be able to know the type barely from its name.

  • I assume the answer is "yes", but I must ask: are you answering entirely from the perspective of Python? Because in other languages your separation of function vs property is not always true; it's also not true that a function "must perform an action". Is this the convention in Python? (I write Python but haven't read all the PEPs and I'm definitely NOT an expert. I didn't downvote, BTW). – Andres F. Oct 20 '16 at 14:29
  • @AndresF.: I'm answering from the perspective of Python. In languages such as Java where properties don't exist, getSomething and setSomething are the usual names used instead of properties. – Arseni Mourzenko Oct 20 '16 at 19:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.