面向对象

面向对象

特点:封装、继承、多态

  • python 一切皆对象
  • 所有的数据类型都是一个类
  • 所有的类型值都是一个具体的对象

自定义类

  • 回想函数

      def func():
      	pass
    
  • 类的定义

      class 类名:
      	def __init__(self, *args, *kwargs):
      		属性 = 'a'
      	
      	def 
      #属性的调用
      类名.属性
    

类属性的补充

	一:我们定义的类的属性到底存到哪里了?有两种方式查看
	dir(类名):查出的是一个名字列表
	类名.__dict__:查出的是一个字典,key为属性名,value为属性值
	
	二:特殊的类属性
	类名.__name__# 类的名字(字符串)
	类名.__doc__# 类的文档字符串
	类名.__base__# 类的第一个父类(在讲继承时会讲)
	类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
	类名.__dict__# 类的字典属性
	类名.__module__# 类定义所在的模块
	类名.__class__# 实例对应的类(仅新式类中)
	
	类属性的补充	

对象的功能

  • 调用属性
  • 调用方法

类名的功能

类的组合

1. 继承性

  • 父类(基类、超类)

  • 子类(派生类)

  • 继承是创建新类的方式,一个类可以继承一个或多个父类

      class A:pass
      class B:pass
      class A_son(A):pass
      class AB_son(A, B):pass
    
  • .__bases__查看子类继承的父类

      print(A_son.__bases__)
      #结果
      (<class '__main__.A'>,)	
      
      #所有类的基类 -新式类
      print(A.__bases__)
      #结果
      (<class 'object'>,)	#object类的最顶端的类
    
    • python3中没有没有父类的类
  • 小练习

      #狗类 吃 喝 看门
      #鸟类  吃 喝 下蛋
      
      #动物类
      class Animal:
          def eating(self):
              print('我正在吃')
      
          def drink(self):
              print('我正在喝水')
      
      #狗类
      class Dog(Animal):
          def kan_men(self):
              print('我能看门')
      
      #鸟类
      class Brid(Animal):
          def xia_dan(self):
              print('我能下蛋')
      
      #实例化狗
      xiao_hei = Dog()
      #实例化鸟
      tuo_niao = Brid()
      
      xiao_hei.drink()
      xiao_hei.eating()
      xiao_hei.kan_men()
      
      tuo_niao.drink()
      tuo_niao.eating()
      tuo_niao.xia_dan()	
      #结果
      我正在喝水
      我正在吃
      我能看门
      我正在喝水
      我正在吃
      我能下蛋
    
  • 子类中的方法会覆盖父类中的方法

  • 子类中和父类具有相同方法时又想调用父类的方法

  • 继承和派生

单继承

- 派生属性

		#创建一个父类,具有name属性
		class Father:
			def __init__(self, name):
				self.name = name
		
		#创建一个子类,具有name和age属性
		class Chrld(Father):
			def __init__(self, age):
				Father.__init__(self, name)	#继承父类的属性				
				self.age = age	#派生子类特有的属性
- 派生方法
	- 父类没有的方法子类有的方法叫派生方法
	- 如果父类里有子类的方法,子类的方法会覆盖父类的方法
  • super()关键字继承

    • super可以在类的外部使用,调用父类的方法

      • super(Chidren, Chidrend的实例).父类方法名(*args, *kwargs)
    • super(类名, self).方法名(*args, *kwargs)

    • 等同于类名.方法名(self, *args, *kwargs)

    • super()遵循广度优先继承

        class Animal:
        	def __init__(self, name):
        		self.name = name
        
        class Dog(Animal):
        	def __init__(self, age)
        		super().__init__(name)	#继承父类的__init__方法,
        		#相当于Animal.__init__(self, name),
        		#这个方法的全写是super(Animal, self).__init__(name)
        		self.age = age
      
  • 类的继承和抽象

    • 抽象即类似比较像的
    • 继承是抽象的结果
    • 继承是类和类的关系

多继承

  • 新式类继承遵循广度优先继承
    • 钻石继承
    • 漏斗继承
    • 小乌龟继承
  • 经典类是深度优先继承
    • 经典类指python2.x
  • pthon3均是新式类

接口类和抽象类

  • 接口类和抽象类都是对面向对象开发的规范

接口类

  • 继承接口类必须具有接口类中被装饰的函数

      #定义一个接口类(规范类函数)
      from abc import absrtactmethod, ABCMeta
      class Jie_Kou(metaclass=ABCMeta)	#加上一个参数
      	@abstractmethod	#装饰器
      	def func1(self):
      		pass
      	
      	@abstractmethod	#装饰器
      	def func2(self):
      		pass
    
  • 接口隔离原则

    • 使用多个单一的接口,而不使用一个总接口。即客户端不应该依赖的那些不需要的接口

抽象类

  • 抽象类也是一种规范
  • 一般是单继承
  • 子类继承的父类功能一致
  • 多继承的情况由于功能比较复杂,所以不容易抽象出相同功能的类

2. 多态性

  • 一个事物有多种形态
  • 一个类有多种形态
  • python语言是动态强类型语言
  • 鸭子类型
    • 不崇尚根据继承所带来的相似
    • 我只是自己实现我自己的代码就可以了
    • 如果两个类恰好相似并不产生兄弟关系,而是鸭子类型

3. 封装性

  • 将变量和函数都放进一个类中

封装的私有方法和私有属性

  • 利用双下划线来定义私有属性和方法

  • 所有的私有变量和私有方法是人为不想让你在类的外部使用,不是不能调取而是不想让你调取

      class Person():
      	def __init__(self, name, age):
      		self.name = name
      		self.__age = age	#私有属性,只能内部调,外部不能调取
      		
      	def func1(self):	#用公有方法调用私有属性
      		print(name)
      		print(__age)	#在类的内部,正常调用
    
      	def __func2(self):	#私有方法,只能内部调用
      		pass
      		
      #实例化对象
      alex = Person()
      alex.name
      alex.__age	#报错,找不到这个属性
      alex._Person__age	#正常调用,调用类中私有属性__age
      
      alex.func1()
      alex.__func2()	#报错,找不到这个方法
      alex._Person__func2()	#正常调用
    
  • 保护属性,不想让外界直接更改

      class Protect():
      	def __init__(self, name)
      		self.__name = name	#将属性name私有化
      		
      	def get_name():	#获取__name的值
      		return self.__name
      		
      	def set_name(newName):	#更改__name的值
      		self.__name = newName
      		return self.__name
    
  • 保护属性不想让子类继承

      	class Father():
      		def __init__(self, name):
      			self.__name = name
      			
      	class 	Child(Father):
      		def __init__(self, age):
      			super.__init__(name)	#这一步会报错,父类的私有属性子类无法调用
      	child = Child()	#报错,无法找到_Child__name
    

封装里的内置函数

@property将函数伪装成属性

@私有变量名.setter设置私有变量的值

@私有变量名.deleter使用del关键字调用修饰的方法

from math import pi

#定义一个圆类	
class	Circle():		
	def __init__(self, r)
		self.r = r
		
	#圆面积
	@property
	def area(self):
		return self.r**2*pi
	
	@property		
	#圆周长
	def perimeter(self):
		return 2*self.r*pi

#实例化一个圆
circle = Circle(1)	#实例化半径为1的圆
print(circle.area)	#直接调用圆面积计算的方法返回圆面积
print(circle.perimeter)	#直接调用圆周长的方法返回圆周长

伪装成属性后修改属性的值

  • 通过这种方法修改了私有变量的值
  • 被修饰的两个方法的名最好和私有变量名一样,这样伪装的才能彻底
    • 私有变量的查看、修改、删除

        class Father():
        	def __init__(self, name):
        		self.__name = name
        	
        	#查看
        	@property	#伪装装饰方法成属性
        	def name(self):
        		return self.__name
        	
        	#修改
        	@name.setter	#提供可修改的方法,装饰器的名字必须是伪装方法的名字.setter
        	def name(self, newName):
        		self.__name = newName
        	
        	#删除
        	@name.deleter	#提供del调用的方法,并不提供删除
        	def name(self, newName):
        		print('测试的代码,测试不删除')	#这是测试的代码
        		del self__name	#这里才是提供删除的原因
        	
        c = Father(1)
        print(c.name)
        c.name = 2	#可以修改__name的属性
        print(c.name)	
        del c.name	#使用del可以调用@deleter装饰的函数
        print(c.name)	
        #结果
        1
        2	
        测试的代码,测试不删除
        报错,找不到_Father__name
      

类方法classmethod

  • 只涉及静态属性的时候使用

      #建立一个货物的类
      class Goods():
      	__discount = 0.5	#这个类具有折扣的通用属性
      	def __init__(self, name, price):
      		self.name = name	#商品名
      		self.__price = price	#商品价格,私有变量,不想让其他人看到
      	
      	@property	#伪装属性用于查看	
      	def price(self):
      		return self.__price * Goods.__discount
      	
      	@classmethod	#类方法
      	def change_discount(cls, new_discount):	#cls参数指代Goods,指代类名,可以是其他参数但是不建议改变
      		cls.__discount = new_discount
      
      #直接外部修改类的通用属性
      Goods.change_discount(0.8)	#将折扣0.5变成0.8,直接调用类名.函数名修改类方法
    

静态方法staticmethod

  • 可以省略参数self创建类中的方法

  • 在完全面向对象的程序中

  • 如果一个函数即和对象没有关系也和类没有关系

  • 静态方法和静态属性对象都能够调用的,不过一般情况下推荐用类名调用

      class Login():
      	def __init__(self, name, password):
      		self.name = name
      		self.password = password
      		
      	@staticmethod	#静态方法
      	def get_us_pw():	#注意这里没有参数self
      		user = input('User:')
      		password = input('Password')
      		Login(name, password)
      
      #调用
      Login.get_us_pw()
    
posted @ 2018-09-09 20:31  小白的蟒蛇  阅读(93)  评论(0编辑  收藏  举报