• Python 实例方法、类方法、静态方法的区别与作用以及私有变量定义和模块导入的区别


    python中至少有三种比较常见的方法类型,即实例方法,类方法、静态方法。它们是如何定义的呢?如何调用的呢?它们又有何区别和作用呢?且看下文。

    首先,这三种方法都定义在类中。下面我先简单说一下怎么定义和调用的。(PS:实例对象的权限最大。)

    实例方法

        定义:第一个参数必须是实例对象,该参数名一般约定为“self”,通过它来传递实例的属性和方法(也可以传类的属性和方法);

        调用:只能由实例对象调用。

    类方法

        定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法);

        调用:实例对象和类对象都可以调用。

    静态方法

        定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;

        调用:实例对象和类对象都可以调用。

    实例方法

    简而言之,实例方法就是类的实例能够使用的方法。这里不做过多解释。

    类方法

    使用装饰器@classmethod。

    原则上,类方法是将类本身作为对象进行操作的方法。假设有个方法,且这个方法在逻辑上采用类本身作为对象来调用更合理,那么这个方法就可以定义为类方法。另外,如果需要继承,也可以定义为类方法。

     类方法可以由类调用,而且因为传入了参数cls,故也可以由实例来调用。

    静态方法两者都能调用

     总结成一张表就是:

     

    譬如,我想定义一个关于时间操作的类,其中有一个获取当前时间的函数。

    import time
    
    class TimeTest(object):
        def __init__(self, hour, minute, second):
            self.hour = hour
            self.minute = minute
            self.second = second
    
        @staticmethod
        def showTime():
            return time.strftime("%H:%M:%S", time.localtime())
    
    
    print(TimeTest.showTime())
    t = TimeTest(2, 10, 10)
    nowTime = t.showTime()
    print(nowTime)

    如上,使用了静态方法(函数),若要获得当前时间的字符串时,并不一定需要实例化对象,此时对于静态方法而言,所在类更像是一种名称空间。

    其实,我们也可以在类外面写一个同样的函数来做这些事,但是这样做就打乱了逻辑关系,也会导致以后代码维护困难。

    静态方法、类方法使用区别或者说使用场景

    由于python类中只能有一个初始化方法,不能按照不同的情况初始化类。

    # coding:utf-8
    class Book(object):
     
        def __init__(self, title):
            self.title = title
     
        @classmethod
        def class_method_create(cls, title):
            book = cls(title=title)
            return book
     
        @staticmethod
        def static_method_create(title):
            book= Book(title)
            return book
     
    book1 = Book("use instance_method_create book instance")
    book2 = Book.class_method_create("use class_method_create book instance")
    book3 = Book.static_method_create("use static_method_create book instance")
    print(book1.title)
    print(book2.title)
    print(book3.title)

    运行结果:

    use instance_method_create book instance
    use class_method_create book instance
    use static_method_create book instance

    特别说明,静态方法也可以实现上面功能,当静态方法每次都要写上类的名字,不方便。

    类中静态方法方法调用静态方法和类方法调用静态方法例子。
    下面的代码,静态方法调用另一个静态方法,如果改用类方法调用静态方法,可以让cls代替类,

    让代码看起来精简一些。也防止类名修改了,不用在类定义中修改原来的类名。

    # coding:utf-8
    class Foo(object):
        X = 1
        Y = 2
     
        @staticmethod
        def averag(*mixes):
            return sum(mixes) / len(mixes)
     
        @staticmethod
        def static_method():  # 在静态方法中调用静态方法
            print "在静态方法中调用静态方法"
            return Foo.averag(Foo.X, Foo.Y)
     
        @classmethod
        def class_method(cls):  # 在类方法中使用静态方法
            print "在类方法中使用静态方法"
            return cls.averag(cls.X, cls.Y)
     
    foo = Foo()
    print(foo.static_method())
    print(foo.class_method())

    运行结果:

    在静态方法中调用静态方法
    1
    在类方法中使用静态方法
    1

    继承类中的区别 

    从下面代码可以看出,如果子类继承父类的方法,子类覆盖了父类的静态方法,
    子类的实例继承了父类的static_method静态方法,调用该方法,还是调用的父类的方法和类属性。

    子类的实例继承了父类的class_method类方法,调用该方法,调用的是子类的方法和子类的类属性。

    # coding:utf-8
    class Foo(object):
        X = 1
        Y = 14
     
        @staticmethod
        def averag(*mixes):  # "父类中的静态方法"
            return sum(mixes) / len(mixes)
     
        @staticmethod
        def static_method():  # "父类中的静态方法"
            print "父类中的静态方法"
            return Foo.averag(Foo.X, Foo.Y)
     
        @classmethod
        def class_method(cls):  # 父类中的类方法
            print "父类中的类方法"
            return cls.averag(cls.X, cls.Y)
     
     
    class Son(Foo):
        X = 3
        Y = 5
     
        @staticmethod
        def averag(*mixes):  # "子类中重载了父类的静态方法"
            print "子类中重载了父类的静态方法"
            print "666 ",mixes
            return sum(mixes) / 3
     
    p = Son()
    print "result of p.averag(1,5)"
    print (p.averag(1,5))
    print "result of p.static_method()"
    print(p.static_method())
    print "result of p.class_method()"
    print(p.class_method())

    结果如下:

    result of p.averag(1,5)
    子类中重载了父类的静态方法
    666  (1, 5)
    2
    result of p.static_method()
    父类中的静态方法
    7
    result of p.class_method()
    父类中的类方法
    子类中重载了父类的静态方法
    666  (3, 5)
    2

    一、私有变量的定义

    在Python中,有以下几种方式来定义变量:

    • xx:公有变量
    • _xx:单前置下划线,私有化属性或方法,类对象和子类可以访问,from somemodule import *禁止导入
    • __xx:双前置下划线,私有化属性或方法,无法在外部直接访问(名字重整所以访问不到)
    • __xx__:双前后下划线,系统定义名字(不要自己发明这样的名字)
    • xx_:单后置下划线,用于避免与Python关键词的冲突

    如以下例子所示,我在test类中定义了num,_num 和 __num三个属性,并创建了test的类对象t,对这三个属性进行访问,__num不能被访问到

    复制代码
    class test(object):
        def __init__(self):
            self.num = 10
            self._num = 20
            self.__num = 30
    
    t = test()
    print(t.num)    # 10
    print(t._num)   # 20
    # print(t.__num)  # AttributeError: 'test' object has no attribute '__num'
    复制代码

    可以使用命令dir查看t中的属性和方法,__num的名字已经被重整为“_test__num”了,可以使用t._test__num对__num进行访问

    注:虽然私有变量可以通过_类名__变量名来访问,但强烈建议不要这样做

    二、使用不同方法导入模块,模块中私有变量的使用区别

    在使用不同方法导入模块后,是否能使用模块中的私有属性和方法,有以下两种情况

    • 在使用 from somemodule import * 导入模块的情况下,不能导入或使用私有属性和方法
    • 在使用 import somemodule 导入模块的情况下,能导入并使用私有属性和方法

    https://blog.csdn.net/helloxiaozhe/article/details/79940321

    https://www.cnblogs.com/jayliu/p/9030725.html

    https://www.cnblogs.com/wcwnina/p/8644892.html

  • 相关阅读:
    quick-cocos2dx 3.5集成protobuf
    lua和luajit在cocos2dx mac模拟器的简单测试
    cocos2dx-lua手游客户端框架设计
    cocos2dx动画技术选型
    lua中的面向对象
    html 学习
    OC 与js 互相调用
    Carthage的安装和使用
    Bomb后端云使用
    FMDB简单使用
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/3775838.html
Copyright © 2020-2023  润新知