Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CapWords conventions: get_MyClass or get_my_class

This is a style conventions question.

PEP8 convention for a class definition would be something like

class MyClass(object):
    def __init__(self, attri):
        self.attri = attri

So say I want to write a module-scoped function which takes some data, processes it, and then creates an instance of MyClass.

PEP8 says that my function definitions should have lowercase_underscore style names, like

def get_my_class(arg1, arg2, arg3):
    pass

But my inclination would be to make it clear that I'm talking about MyClass instances like so

def get_MyClass(arg1, arg2, arg3):
    pass

For this case, it looks trivially obvious that my_class and MyClass are related, but there are some cases where it's not so obvious. For example, I'm pulling data from a spreadsheet and have a SpreadsheetColumn class that takes the form of a heading attribute and a data list attribute. Yet, if you didn't know I was talking about an instance of the SpreadsheetColumn class, you might think that I'm talking about a raw column of cells as they might appear in an Excel sheet.

I'm wondering if it's reasonable to violate PEP8 to use get_MyClass. Being new to Python, I don't want to create a habit for a bad naming convention.

I've searched PEP8 and Stack Overflow and didn't see anything that addressed the issue.

like image 774
Ben Mordecai Avatar asked Jan 25 '13 21:01

Ben Mordecai


People also ask

Should Python functions be capitalized?

According to PEP8, function and variable names should be lowercase with words separated by underscores.

How do you name a method in Python?

Method name in PythonUse only lowercase in method names. An underscore should separate words in a method name. Non-public method name should begin with a single underscore. Use two consecutive underscores at the beginning of a method name, if it needs to be mangled.


2 Answers

Depending on the usage of the function, it might be more appropriate to turn it into a classmethod or staticmethod. Then it's association with the class is clear, but you don't violate any naming conventions.

e.g.:

class MyClass(object):
     def __init__(self,arg):
         self.arg = arg

     @classmethod
     def from_sum(cls,*args):
         return cls(sum(args))

inst = MyClass.from_sum(1,2,3,4)
print inst.arg  #10
like image 150
mgilson Avatar answered Nov 15 '22 08:11

mgilson


Let's take a step back. Usually, you don't want to do this at all, so the naming convention is the least of your worries.

First, normally, you don't care what actual class or type something is. This is what duck typing is all about. You don't want a SpreadsheetColumn instance, you want something that you can use as a spreadsheet column. It may be an instance of SpreadsheetColumn, or of a subclass, or of some proxy class, or of some mock class for testing—whatever it is, you don't care, as long as it looks and works like a column.

Notice that, even in static languages like Java and C#, factory functions (or objects) usually don't create an instance of a specific class, they create an instance of any class that implements a specific interface. In Python, that's usually implicit. (And, when it's not, it's usually because you're using something like PEAK or Twisted, and you should follow their coding style for protocols or interfaces.)

So, your factory function should be called get_column, not get_SpreadsheetColumn.

When the function is more of an "alternate constructor" than a factory, then mgilson's answer is the way to go. See chain() and chain.from_iterable() in itertools from a good standard library example.

But notice that this isn't very common in the standard library, most of the popular modules on PyPI, etc. And there's a good reason. Usually, you can just use a single constructor with default-valued parameters, keyword parameters, or at worst *args and **kwargs. If this makes the API too confusing for human readers, or too ambiguous to code, that's when you need an alternate constructor. Otherwise, you don't.

Sometimes, you really do need a factory that creates objects of a concrete type, and that concrete type is a part of the interface that the caller needs to know about. As I mentioned above, this is pretty rare even in static languages, and it's even rarer in Python, but it does come up. And then, you really do need an answer to your original question.

In that case, I think I would name the function something ugly and unusual like get_MyClass or get_MyClass_instance. It ought to stick out immediately, because anyone reading my code will probably need to figure out why I'm explicitly getting a MyClass instead of a thing in order to understand the rest of my code.

like image 44
abarnert Avatar answered Nov 15 '22 08:11

abarnert