python面向对象

一.相关定义

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • 局部变量:定义在方法中的变量,只作用于当前实例的类。
  • 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
  • 实例化:创建一个类的实例,类的具体对象。
  • 方法:类中定义的函数。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

二.类

  相关知识:

  1.基本形式
    class 类名:
      """注释"""

      类体

  2.类规范:首字母大写
  3.类名加. 调用属性和方法
  4.方法

    - dir(类):查看属性和方法,返回一个列表
    - 类名.__dict__:查看属性可方法,返回键值对
    - __name__:查看类名

    - __doc__:文档信息,不能被继承,没有返回None

    - __base__:查看继承于哪个类

    - __module__:查看来自于哪个模块

    - __class__:查看哪个类来的类由type来

三.实例

  1.实例=类名() --》生产实例
  2.__init__初始化,在产生实例的过程中会执行类的 __init__方法
  3.实例也可以通过 . 访问类的属性
  4.__dict__中 实例只绑定了属性,没有绑定方法,通过 . 访问类的方法执行
  5.self相当于实例本身,定义方式中的(self),全部相当于把实例传入进去
    实例.方法() <==>类.方法(实例)

 1 class Dog():  # 定义Dog类,首字母大写
 2     """
 3     定义Dog类
 4     """
 5 
 6     def __init__(self, name, type):
 7         self.name = name
 8         self.type = type
 9 
10     def eat(self):
11         print('%s在吃东西' % self.name)
12 
13     def run(self):
14         print('%s在奔跑' % self.name)
15 
16 
17 d = Dog('pp', '柯基')  # 实例化Dog
18 print(d.name)
19 print(d.type)
20 d.eat()
21 d.run()
22 print(d.__dir__())  # 查看全部属性和内置方法
23 print(d.__dict__)  # 查看属性,返回键值对,实例只绑定了属性,没有绑定方法,通过 . 访问类的方法执行
24 print("---------------------------")
25 print(Dog.__dict__)  # 查看类的属性和方法,返回键值对
26 print(dir(Dog))  # 查看类的属性和方法,返回列表
27 print(Dog.__name__)  # 查看类名
28 print(Dog.__doc__)  # 查看文档
29 print(Dog.__module__)  # 查看来自哪个模块
30 print(Dog.__base__)  # 查看继承于哪个类
31 print(Dog.__class__)  # 查看由哪个类来的,元类是type

结果

 1 pp
 2 柯基
 3 pp在吃东西
 4 pp在奔跑
 5 ['name', 'type', '__module__', '__doc__', '__init__', 'eat', 'run', '__dict__', '__weakref__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
 6 {'name': 'pp', 'type': '柯基'}
 7 ---------------------------
 8 {'__module__': '__main__', '__doc__': '\n    定义Dog类\n    ', '__init__': <function Dog.__init__ at 0x0000023A817B5378>, 'eat': <function Dog.eat at 0x0000023A8285E158>, 'run': <function Dog.run at 0x0000023A8285E1E0>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>}
 9 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'eat', 'run']
10 Dog
11 
12     定义Dog类
13     
14 __main__
15 <class 'object'>
16 <class 'type'>

 

四.类和实例的增删改查

  类

 1 class Dog():  # 定义Dog类,首字母大写
 2     x = 1
 3 
 4     def __init__(self, name, type):
 5         self.name = name
 6         self.type = type
 7 
 8     def eat(self):
 9         print('%s在吃东西' % self.name)
10 
11     def run(self):
12         print('%s在跑' % self.name)
13 
14 
15 d = Dog('xiaohong', '柯基')
16 Dog.eat(d)  # 当调用类方法时需要手动传入实例对象,等价于d.eat()
17 
18 Dog.y = 2  # 增加属性
19 Dog.x = 10  # 修改类属性
20 
21 def eat(self):
22     print('修改后-->%s在吃' % self.name)
23 
24 
25 Dog.eat = eat  # 修改类方法
26 print(Dog.__dict__)
27 d.eat()
28 del Dog.y  # 删除类属性

  实例

 1 d.y = 20  # 增加属性,加入的是实例的__dict__字典,与类无关
 2 
 3 
 4 def sleep(self):  # 可以自定义实例的方法,但是注意要穿入参数,当调用类的方法时,会自动将实例传入self中
 5     print('%s正在睡觉' % self.name)
 6 
 7 
 8 d.sleep = sleep  # 增加实例方法
 9 del d.y  # 删除实例属性
10 d.sleep(d)  # 注意此时需要传入self参数
11 d.x=100  # 修改属性,不影响Dog的x的值
12 print(d.__dict__)
13 print(Dog.__dict__)
1 xiaohong正在睡觉
2 {'name': 'xiaohong', 'type': '柯基', 'sleep': <function sleep at 0x000002102FB8C1E0>, 'x': 100}
3 {'__module__': '__main__', 'x': 1, '__init__': <function Dog.__init__ at 0x00000210319B5378>, 'eat': <function Dog.eat at 0x0000021032A4E158>, 'run': <function Dog.run at 0x0000021032A4E1E0>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None}

五.类的相关装饰器和组合

静态属性 @property 
类方法 @classmethod
静态方法 @staticmethod
 1 class Room:
 2     def __init__(self, name, length, width, height):
 3         self.name = name
 4         self.length = length
 5         self.width = width
 6         self.height = height
 7 
 8     @property  # 对于函数属性,可以不同加括号,相当于把函数属性转换成静态属性
 9     def area(self):
10         res = self.length * self.width
11         print('面积是%s' % res)
12         return res
13 
14     @classmethod  # 类方法,不必要传入实例的属性,即不用传入self
15     def tell_info(cls, place):  # 类和实例都可以调用,cls均不需要传入,系统默认将类传入cls
16         print(cls)
17         print('这是一个房子,位于%s' % place)
18 
19     @staticmethod  # 静态方法,与类和实例属性均无关,无法访问类和实例属性
20     def happy(who, what):  # 类和实例均能调用
21         print('%s在房子里干%s,很高兴' % (who, what))
22 
23 
24 r = Room('客厅', 3, 4, 5)
25 print(r.area)
26 r.tell_info('浙江')
27 Room.tell_info('浙江')
28 Room.happy('ppp', 'sing_song')
29 r.happy('ppp', 'sing_song')
1 面积是12
2 12
3 <class '__main__.Room'>
4 这是一个房子,位于浙江
5 <class '__main__.Room'>
6 这是一个房子,位于浙江
7 ppp在房子里干sing_song,很高兴
8 ppp在房子里干sing_song,很高兴

  组合

大类包含小类
把类的实例化放到一个新类里
self.foot=Foot()

 

 1 class Fish:
 2     def __init__(self, type):
 3         self.type = type
 4 
 5     def swim(self):
 6         print('小鱼在快乐的游泳')
 7 
 8 
 9 class Turtle:
10     pass
11 
12 
13 class Pool:
14     def __init__(self, f_num, t_num):
15         self.f_num = f_num
16         self.t_num = t_num
17         self.fish = Fish('鲫鱼')
18         self.turtle = Turtle()
19 
20     def swim(self):
21         print('池塘里有%s只鱼,鱼的类型是%s,%s只乌龟' % (self.f_num, self.fish.type, self.t_num))
22 
23 
24 p = Pool(10, 3)
25 p.swim()
26 # 池塘里有10只鱼,鱼的类型是鲫鱼,3只乌龟

六.三大特性

  继承

    分类:单继承、多继承
    继承顺序:__mro__
  
    含义
      含义一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
      含义二:声明某个子类兼容于某基类,定义一个接口类,子类继承接口类,并且实现接口中定义的方法
    

 1 import abc
 2 
 3 
 4 class AllFile(metaclass=abc.ABCMeta):
 5 
 6     @abc.abstractmethod
 7     def write(self):
 8         pass
 9 
10     def read(self):
11         raise NotImplementedError("必须实现read方法")
12 
13 # 子类必须写write方法
14 # 子类不写read方法,调用read报错,也需要自定义
15 class MyFile(AllFile):
16     def write(self):
17         pass
18     
19     def read(self):
20         pass
21 
22 
23 file = MyFile()
24 file.read()

  属性:1.同名子类不会覆盖父类的方法,是先从子类找,找不到去父类
     2.子类.__dict__没有父类的属性,但是可以调用
     3.在子类中调用父类的方法:super([子类,self]).父类方法()

  多态  

    1.由不同的类实例化得到的对象,调用同一个方法,执行的逻辑不同
    2.不同对象继承于同一父类,但是对父类同一方法有不同的响应行动

 1 print('asd'.__len__())
 2 print([1,2,5,6].__len__())
 3 print({'a:1,''b':1}.__len__())
 4 
 5 
 6 class Hho:
 7     def __init__(self,temp):
 8         self.temp=temp
 9     def state(self):
10         if self.temp<=0:
11             print('温度太低了,水结冰了')
12         if 0<self.temp<100:
13             print('温度合适,状态是水')
14         if self.temp>=100:
15             print('温度太高了,水汽化了')
16 ice=Hho(-3)
17 water=Hho(10)
18 gas=Hho(130)
19 ice.state()
20 water.state()
21 gas.state()

  “开闭”原则:

  • 对扩展开放(Open for extension):允许子类重写方法函数
  • 对修改封闭(Closed for modification):不重写,直接继承父类方法函数

 

  封装

    1.定义:

      在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其含义是其他程序无法调用。要了解封装,离不开“私有化”,就是将类或者是函数中的某些属性限制在某个区域之内,外部无法调用。


    2.实现方法:
      a. _ 单下划线开头:约定是内部属性,但是外部还是可以调用
      b. __ 双下划线开头:外部无法直接调用,但通过 _People__star 调用 --》(_类名__变量名)

    3.接口函数/访问函数:通过内部定义函数访问私有属性,外部可以通过函数访问

      @property 调用者不必关系内部怎么实现的,只需要调用属性即可

 1 class Foo:
 2     __x = 1
 3     __y = 2
 4 
 5     def __init__(self, m, n):
 6         self.__m = m
 7         self.__n = n
 8 
 9     @classmethod  # 封装的函数只能在内部调用,外部不能调用,外部调用需要写成 _类名__属性名
10     def tem(cls):
11         return cls.__x * cls.__y
12 
13     def temp(self):
14         return self.__m * self.__n
15 
16     def __res(self):
17         return self.__x * self.__y
18 
19     def res(self):
20         return self.__x * self.__y
21 
22 
23 f = Foo(5, 6)
24 print(f._Foo__m)
25 print(f.tem())
26 print(f.temp())
27 print(f.res())
28 print(f._Foo__res())
1 5
2 2
3 30
4 2
5 2

七.反射

    1.内置函数
      hasattr(对象,属性):判断是否有属性
      getattr(对象,属性,[设置值]):获得属性,没有设置默认值,如果没有报错,设置了,没有返回设置的值
      setattr(对象,属性,value):设置属性,可以设置函数属性
      delattr(对象,属性):删除属性,不能删类的属性,只能删自己的

    2.补充:动态导入,通过字符串导入模块
      
      m=__import__('m1.t')
      得到的是顶级目录,m1,通过m1.t可以得到t模块


      通过importlib模块,m=importlib.import_module('m1.t')
      得到的是m1下的t模块


    3类的内置函数
      __getattr__:获取不存在的属性时执行
      __getattribute__:获取属性时执行,不管存不存在都执行,不存在时抛出异常AttributeError异常,然后__getattr__执行
      __setattr__:设置属性时执行,self.key=value,需要设置self.__dict__[k]=v ,如果设置self.k=v会无限递归
      __delattr__:删除属性时执行,删除对象属性不存在时也执行,需要设置self.__dict__.pop(item)-->删除的是字典key和value


      注意:继承基本类,重新定义函数,修改方法,注意修改时调用父类方法super(),否则会无限递归


    4.授权(类似于组合)
      file=open(file,mode,encoding)
      通过__getattr__(-->方法不存在时调用),然后返回getatter self.file.write()得到内置文件write方法
      可以重新定义 write() self.file.write() 重写write方法

 1 class Foo:
 2     x = 1
 3 
 4     def res(self):
 5         print('hello')
 6 
 7 
 8 f = Foo()
 9 print(hasattr(Foo, 'x'))
10 setattr(Foo, 'y', 7)
11 print(Foo.__dict__)
12 print(getattr(Foo, 'y', '没有想要的值'))
13 print(hasattr(f, 'x'))
14 setattr(f, 'y', 7)
15 print(f.__dict__)
16 print(getattr(f, 'y', '没有想要的值'))
17 delattr(f, 'y')
18 
19 # True
20 # {'__module__': '__main__', 'x': 1, 'res': <function Foo.res at 0x0000016F23D85378>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None, 'y': 7}
21 # 7
22 # True
23 # {'y': 7}
24 # 7

八.其他知识点

  1.一些内置函数
    isinstance(对象,类) : 对象是否是类实例化来的,类是父类也是True
    issubclass(类1,类2):类1是否是类2的子类,后面可以是元祖
  2.魔法方法
    __getitem__
    __setitem__
    __delitem__
      f1['name']=‘root’  --》 以字典形式操作时调用(容器类)
  3.str与repr
    (return 必须是字符串类型)
    __str__  --》 print()执行时调用,可以定制__str__,得到自己想要的结果
    __repr__ --》 在解释器中执行是调用
      print()先找__str__,找不到再找__repr__
  4.执行forrmat时执行__format__,返回值是必须是字符串
    可以重写定制format

  5.__slots__
    当一个类只有很少的属性但是有很多实例时,可以定义__slots__=['name','age']
    那么__solts__就代替了__dict__,且不能再增加额外的新的属性了
  6.__del__

    a.只有实例删除的时候会删除
    b.程序运行完成时内存释放会回收实例,执行__del__
  7.__call__

    后面加括号,触发执行
  8.__iter__
    只有有这个方法才能转换成迭代器对象,返回可迭代对象
  9.__next__
    设置next的返回值,定义错误raise StopIteration('终止了')
  10.上下文管理协议
    __enter__:with 运行时执行
    __exit__:with代码块执行完后执行

 

 

  

posted @ 2019-03-09 20:27  工藤_小哀  阅读(131)  评论(0编辑  收藏  举报