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.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容