zoukankan      html  css  js  c++  java
  • 面向对象

    面向对象

    特点:封装、继承、多态

    • 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()
  • 相关阅读:
    Best Cow Fences_二分&&DP
    Palindrome_滚动数组&&DP
    Making the Grade_滚动数组&&dp
    BUY LOW, BUY LOWER_最长下降子序列
    Testing the CATCHER_DP
    Best Sequence_DFS&&KMp
    (Your)((Term)((Project)))
    [SOJ] 畅通工程续
    [SOJ] 商人的宣传
    [SOJ] 无路可逃?
  • 原文地址:https://www.cnblogs.com/liliudong/p/9614938.html
Copyright © 2011-2022 走看看