0%

python—面向对象

面向对象

  • 类 方法 实例
  • 封装 继承 多态

类和实例

  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Student(object):

    def __init__(self, name, score):
    self.name = name
    self.score = score

    def print_score(self):
    print('%s: %s' % (self.name, self.score))

    bart = Student('Bart Simpson', 59)
  • 定义类的关键词与java一样 class 括号内为继承的父类.没有父类时,选择 object 作为基类.(object是所有类的基类)

  • 变量比较特殊,不像java中有单独字段.python 类中变量定义是在__init__方法

  • 方法的声明和函数类似. def 方法名 (参数)

    • 类中 第一个参数必须是self,意为创建的实例自身.方法中调用类中其他变量都要通过 self.xxx 访问.
  • 一些必须实现的属性在__init__方法中定义.如示例.第一个参数是 self 之后是具体变量值,在方法内 使用self访问类中定义的变量.

  • Python允许对实例变量绑定任何数据,so just do it😈

访问限制

  • 类似java private 字段的python实现

  • 属性的名称前加上两个下划线 __ 该属性就成为了类的私有属性,只能在实例的内部访问.(self.xxx)

  • 获取/修改,使用 get/set 获取或修改对应属性.(一般在set中可以添加类型检查)

  • 类似__xxx__的变量,双下划线开头,并且以双下划线结尾的,是特殊变量.特殊变量是可以直接访问的,不是private变量.也最好不要定义__xxx__变量名

  • 以下划线开头的实例变量名,例如_name.可以在外部访问的,但是,约定俗成,请直接忽视.

  • 特例:

    • 双下划线开头的实例变量不能直接访问是因为Python解释器对外把__name变量改成了_Student__name.仍然可以通过_Student__name来访问__name变量.

    • 一个错误设置示例:

      1
      2
      3
      4
      5
      6
      7
      8
      >>> bart = Student('Bart Simpson', 59)
      >>> bart.get_name()
      'Bart Simpson'
      >>> bart.__name = 'New Name' # 设置__name变量!
      >>> bart.__name
      'New Name'
      >>> bart.get_name() # get_name()内部返回self.__name
      'Bart Simpson'
    • 如同示例,外部代码直接赋给 bart.__name 不会影响实例中原有属性,只会新增一个属性.究其原因,实例中的属性已经被解释器重命名为了bart._Student__name.

继承和多态

  • 继承和多态概念与java类似.不多语了.
  • 那么重点来了:
  • python本身是动态语言,体现在变量/类等各个方面,自由度极高.在继承上,亦是如此.
    • java中定义一个su方法,调用model类实例实现的run方法.su方法可传入的只有 model类或其子类的实例
    • 但python中 只要是定义了 run方法(别管内容/功能一样不一样)类的实例,都可以作为参数传入 su 方法.
  • java中对类的类型的处理,相当于照猫🐱画虎🐯,传入的起码要是个猫科动物. python 中对类的类型处理,额头写个字,哪怕传入具体对象是个猫头鹰🦉,也当作猫科处理了.

  • note:
    判断一个变量是否是某个类型可以用isinstance()
    1
    2
    >>> isinstance(a, list)
    True

获取对象信息


  • 让我想起了java反射..不过能获取的信息要全多了.

type()

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    >>> type(123)
    <class 'int'>

    >>> type(a)
    <class '__main__.Animal'>

    >>> type(123)==type(456)
    True
  • 判断对象类型

  • 由变量指向函数或者类,也可以用type()判断

  • type返回对应的Class类型,可直接 == 类型判断

  • 判断一个对象是否是函数:

    1
    2
    3
    4
    5
    6
    7
    8
    >>> import types
    >>> def fn():
    ... pass
    ...
    >>> type(fn)==types.FunctionType
    True
    >>> type(abs)==types.BuiltinFunctionType
    True

isinstance()

  • 示例:

    1
    2
    3
    4
    5
    >>> isinstance(h, Husky)
    True

    >>> isinstance([1, 2, 3], (list, tuple))
    True
  • 判断继承关系,一打一个准.

  • 能用type()判断的基本类型也可以用isinstance()判断

  • 总是优先使用isinstance()判断类型,可以将指定类型及其子类“一网打尽”。

dir()

  • 示例:

    1
    2
    >>> dir('ABC')
    ['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
  • 获得一个对象的所有属性和方法.直接返回一个字符串list.

  • 配合getattr()、setattr()以及hasattr(),可以直接操作一个对象的状态.

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>> hasattr(obj, 'x') # 有属性'x'吗?
    True
    >>> obj.x
    9
    >>> hasattr(obj, 'y') # 有属性'y'吗?
    False
    >>> setattr(obj, 'y', 19) # 设置一个属性'y'
    >>> hasattr(obj, 'y') # 有属性'y'吗?
    True
    >>> getattr(obj, 'y') # 获取属性'y'
    19
    >>> obj.y # 获取属性'y'
    19
  • 不存在的属性,会抛出AttributeError的错误,可以传入一个default参数,如果属性不存在,就返回默认值.

    1
    2
    >>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
    404
  • 也可以获得对象的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> hasattr(obj, 'power') # 有属性'power'吗?
    True
    >>> getattr(obj, 'power') # 获取属性'power'
    <bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
    >>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
    >>> fn # fn指向obj.power
    <bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
    >>> fn() # 调用fn()与调用obj.power()是一样的
    81
  • 只有在不知道对象信息的时候,才会去获取对象信息.谨记,谨记.

实例属性和类属性

  • 类似java类中静态变量 与 普通变量区别.

  • 类的属性,直接在类的cclass中声明.

    1
    2
    class Student(object):
    name = 'Student'
  • 访问时,类的属性会被实例的同名属性覆盖,但不会被修改,互相独立.

  • 删除实例属性后,再使用相同的名称,访问到的将是类属性