Non-member vs member functions in Python

前端 未结 5 1823
清歌不尽
清歌不尽 2021-02-18 21:54

I\'m relatively new to Python and struggling to reconcile features of the language with habits I\'ve picked up from my background in C++ and Java.

The latest issue I\

相关标签:
5条回答
  • 2021-02-18 21:54

    A free function gives you the flexibility to use duck-typing for that first parameter as well.

    A member function gives you the expressiveness of associating the functionality with the class.

    Choose accordingly. Generally, functions are created equal, so they should all have the same assumptions about the interface of a class. Once you publish a free function scale, you are effectively advertising that .dX and .dY are part of the public interface of Vector. That is probably not what you want. You are doing this in exchange for the ability to reuse the same function with other objects that have a .dX and .dY. That is probably not going to be valuable to you. So in this case I would certainly prefer the member function.

    For good examples of preferring a free function, we need look no further than the standard library: sorted is a free function, and not a member function of list, because conceptually you ought to be able to create the list that results from sorting any iterable sequence.

    0 讨论(0)
  • 2021-02-18 22:04

    As scale relies on member-wise multiplication of a vector, I would consider implementing multiplication as a method and defining scale to be more general:

    class Vector(object):
        def __init__(self, dX, dY):
            self._dX = dX
            self._dY = dY
    
        def __str__(self):
            return "->(" + str(self._dX) + ", " + str(self._dY) + ")"
    
        def __imul__(self, other):
            if other is Vector:
                self._dX *= other._dX
                self._dY *= other._dY
            else:
                self._dX *= other
                self._dY *= other
    
            return self
    
    def scale(vector, scalar):
        vector *= scalar
    

    Thus, the class interface is rich and streamlined while encapsulation is maintained.

    0 讨论(0)
  • 2021-02-18 22:09

    Interesting question.

    You're starting from a different place than most questions coming from Java programmers, which tend to assume that you need classes when you mostly don't. Generally, in Python there's no point in having classes unless you're specifically doing data encapsulation.

    Of course, here in your example you are actually doing that, so the use of classes is justified. Personally, I'd say that since you do have a class, then the member function is the best way to go: you're specifically doing an operation on that particular vector instance, so it makes sense for the function to be a method on Vector.

    Where you might want to make it a standalone function (we don't really use the word "member" or "non-member") is if you need to make it work with multiple classes which don't necessarily inherit from each other or a common base. Thanks to duck-typing, it's fairly common practice to do this: specify that your function expects an object with a particular set of attributes or methods, and do something with those.

    0 讨论(0)
  • 2021-02-18 22:10

    Prefer non-member non-friend functions to member functions

    This is a design philosophy and can and should be extended to all OOP Paradigm programming languages. If you understand the essence of this, the concept is clear

    If you can do without requiring private/protected access to the members of a Class, your design do not have a reason to include the function, a member of the Class. To think this the Other way, when designing a Class, after you have enumerated all properties, you need to determine the minimal set of behaviors that would be sufficient enough to make the Class. Any member function that you can write using any of the available public methods/member functions should be made public.

    How much is this applicable in Python

    To some extent if you are careful. Python supports a weaker encapsulation compared to the other OOP Languages (like Java/C++) notably because there is no private members. (There is something called Private variables which a programmer can easily write by prefixing an '_' before the variable name. This becomes class private through a name mangling feature.). So if we literally adopt Scott Meyer's word totally considering there is a thin like between what should be accessed from Class and what should be from outside. It should be best left to the designer/programmer to decide whether a function should be an integral part of the Class or Not. One design principle we can easily adopt, "Unless your function required to access any of the properties of the class you can make it a non-member function".

    0 讨论(0)
  • 2021-02-18 22:20

    Look at your own example - the non-member function has to access the data members of the Vector class. This is not a win for encapsulation. This is especially so as it changes data members of the object passed in. In this case, it might be better to return a scaled vector, and leave the original unchanged.

    Additionally, you will not realise any benefits of class polymorphism using the non-member function. For example, in this case, it can still only cope with vectors of two components. It would be better if it made use of a vector multiplication capability, or used a method to iterate over the components.

    In summary:

    1. use member functions to operate on objects of classes you control;
    2. use non-member functions to perform purely generic operations which are implemented in terms of methods and operators which are themselves polymorphic.
    3. It is probably better to keep object mutation in methods.
    0 讨论(0)
提交回复
热议问题