02.Python面向对象

Python面向对象基础

面向对象三个主要的特性是封装、抽象和继承;所谓封装,通俗的理解就是打包、集合,把一些零碎的命令封成一个工具,以后再用的时候,可以直接使用这个做好的工具而无需再去组装,一方面节省工作量,另一方面也不需再次测试工具的正确性;而抽象就是简化,简化到只剩下总体结构。一本书的目录,就是这本书的抽象,每个目录下对应的内容,是具体的实现;继承,是不劳而获的优越技能,继承而来,如同继承祖辈的财产,在面向对象编程中,继承是类继承其父类(或称基类)的财产,即方法,属性;从继承这一特性可以引出多态的特性,多态,多种形态,适应多种形态,如一个方法,能够对应多种要求的使用(方法重载)就是一种多态。

python支持多重继承,派生类可以重写父类所有的方法;原生python没有抽象类和接口的概念,不过可以借助第三方库abc.py实现抽象接口的功能。

python类

  • class定义语法
# coding=utf-8

class MyClass:
   """
  this is a  sample class
  """
    def __init__(self):
        # this method just like a constructor
        self.number = 100
        self.x = "x"
        self.y = "y"
        print("this is init method")

    # class variable
    name = "myClass"

    def func(self):
        self.name = "func"
        self.number = 200
        
    #使用this替换self
    def func2(this):
        print(this.number)
    
    def func3(self):
        self.staticfunc()
        self.classfunc()
        self.func()

    #class方法
    @classmethod
    def classfunc(cls):
        print("classmethod")
      
    #静态方法
    @staticmethod
    def staticfunc():
        MyClass.classfunc()
        print("staticmethod")


  1. 定义一个类使用class <className>(baseclass);
  2. __init__()方法是python类的constructor方法,在创建类的实例对象时会调用此方法;
  3. 上面的name变量是类变量,是此类的所有实例对象所共享的变量,即大家都可以读写这个name变量;
  4. 在方法内部定义的self.xx变量,是实例变量(属性),是由各个实例对象所拥有的属性,其他对象无法干涉;
  5. 关于方法定义时,第一个self参数,这个是固定的,是在实例对象调用方法时,隐式地将对象自身传给方法内部,所以才有self.xx的引用属性的方式,和java的this差不多,这里也可以把self改成this,只是默认这个名字叫self而已。
  6. @classmethod注解的方法,是类方法,可以由类名.方法名的方式调用,和java的静态方法类似
  7. @staticmethod注解的是静态方法,和类方法很相似,在使用上除了类方法隐式传递了类对象,似乎没有多大区分。
  • 实例化
obj = MyClass()
obj.func()
obj.classfunc()  # 实例对象和类都可以直接调用类方法和静态方法,反过来则不行
obj.staticfunc()
MyClass.classfunc()
MyClass.staticfunc()
obj.func3()
  • 动态属性
    class MyPlainClass:
        pass

    plainobj = MyPlainClass()
    #动态添加
    plainobj.name = "newname"
    plainobj.address= "ch"
    print(plainobj.name)
    print(plainobj.address)
    
    # output
    """
    newname
    ch
    """
     
    # 动态删除
    del plainobj.address
    print(plainobj.address)
    
    # output
    """
    newname
Traceback (most recent call last):

  File "F:/source/pyproject/TestClass.py", line 2, in <module>
    class MyClass:
  File "F:/source/pyproject/TestClass.py", line 42, in MyClass
    print(plainobj.address)
AttributeError: 'MyPlainClass' object has no attribute 'address'
    """
  • 继承
class MyChild(MyClass):
    def func(self):
        self.name = "mychild"
        print("in mychild func")

    @staticmethod
    def staticfunc():
        print("in mychild staticfunc")

def testInheritance():
    pa = MyClass()
    child = MyChild()
    pa.func()
    child.func()
    pa.staticfunc()
    child.staticfunc()
if __name__ == '__main__':
    testInheritance()
    
# output:
"""
this is init method
this is init method
in mychild func
classmethod
staticmethod
in mychild staticfunc
"""
  1. 子类方法的查找规则,是自内而外的,和方法内的变量find规则一致,如果子类自己定义了或者重写了,就直接使用自己的,如果没有则去父类找,如__init__()方法
  • 变量访问控制
class MyClass2:
    # private class variable 只有类对象自己能访问,连子类对象也不能访问到这个数据
    __name = "name"
    # protected class variable  只有类对象和子类对象自己能访问到这些变量;
    _protectname = "pttname"
    # normal class variable
    addr = "where"
    #__object__ # special, python system use, user should not define like it
    
    # access private/ protected and normal  variable in function
    def __init__(self):
        self.__name = "init_name"
        self._protectname = "init_protected_name"
        self.addr = "init_addr"
        self.__objname = "init_private_obj_name"

    def get(self):
        print(self.__name)
        print(self._protectname)
        print(self.addr)
        print(self.__objname)


def testprivate():
    pri = MyClass2()
    pri.get() 
    print(pri._protectname)  
    """
init_name
init_protected_name
init_addr
init_private_obj_name
init_protected_name
    """
    
    pri.__objname # -->AttributeError: 'MyClass2' object has no attribute '__objname'
    pri.__name   #--> AttributeError: 'MyClass2' object has no attribute '__name'

    print(pri._protectname)
    pri._protectname = "what"
    print(pri._protectname)
    """
    init_protected_name
    what
    """

双下划线定义的变量是私有变量,仅仅本类内部可以访问,和java一样,实例对象也不能直接使用obj.attribute的方式来访问属性;对私有变量的访问,可以使用类似java的pojo的方式访问。

单下划线定义的是保护变量,原则上不允许直接访问,但外部还是可以访问到这个变量,只是一个约定。

protected变量,推荐使用访问器访问。

    @property
    def protectname(self):
        return self._protectname

The end.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容