面向对象总结

类的定义和对象的产生

# 在程序中,必须先定义类,再调用类产生对象

class Student():
    pass



# 定义类发生了什么?
"""
	1、会立即执行类体代码
	2、产生类的名称空间,把类中得到的名字都丢到类的名称空间去
	3、把类的名称空间绑定给__dict__,调用方式为:类名.__dict__
"""

# 产生对象
调用类产生一个对象,这个对象默认是空对象
obj = 类名()
'''得到的对象也有自己的名称空间'''
obj.__dict__

定制对象自己独有的属性

class Student():
    
    def __init__(self, name, age)
    	self.name = name
    	self.age = age
        
obj = Student('xxx', 18)
obj.name  -----> 'xxx'
obj.age   -----> 18
obj.__dict__ ----> {'name':'xxx', 'age:18'}

属性的查找顺序

# 类属性(不考虑继承的情况下)
> 直接在类中自己查找,找不到就报错

# 对象属性(不考虑继承的情况下)
> 先从自己的名称空间中查找,再从产生这个对象的类中找,找不到就报错

绑定方法与非绑定方法

# 绑定方法:绑定给类的方法和绑定给对象的方法
1、绑定给对象的方法:
	> 对象来调用:会把对象自己当成第一个参数传给方法的第一个参数self
	> 类来调用绑定给对象的方法:类名来调用,方法里有几个参数就给几个参数,包括self
2、绑定给类的方法:
	'''将方法绑定给类的话需要在方法头上加个装饰器:@classmethod'''
    > 类来调用:会将类名当做第一个参数传给方法的第一个参数cls
    
# 非绑定方法
	'''在方法头上加个装饰器:@staticmethon'''
	> 类与对象都可以调用,相当于普通函数,有几个参数就要给几个参数

隐藏属性

# 隐藏属性就是在属性名或者方法名前面加上__
'''
	1、在类的定义阶段隐藏的,名字发生了变形:_类名__属性名
	2、在类的外部原则上是不能用了,非要用也可以用
	3、对外不对内
'''
# 为什么要隐藏?
	> 在类的内部开放一个接口来返回类中隐藏的属性,可以更好的对属性作限制

property(将方法伪装成属性)

'''把方法伪装成属性后,以后调用方法的时候,就不用加括号了,直接点属性名即可'''
eg:
	> @property
	> @方法名.setter
 	> @方法名.deleter
    
    # 另外一种用法
        在类的内部使用property()函数
    class Foo:
    	xxx = property('get_country', 'set_country', 'del_country')
    obj = Foo()
    obj.xxx
    obj.xxx = 'a'
    del obj.xxx 

继承

'''
	1、继承是新建类的一种方式,被创建出来的类是子类,被继承的类是父类
	2、继承是为了减少类与类之间的代码冗余问题
	3、在子类括号里面写上继承父类的名字
	4、子类可以遗传父类所有的属性和方法
'''
eg:
	class Foo():
        pass
    
    class Bar(Foo):
        pass
    
 '''
 		1. 经典类和新式类的查找
			在Python2中会出现经典类
		2. 经典类的属性查找顺序:深度优先
		3. 新式类的属性差债:广度优先
 '''

super和mro

	# python2:super(Student,self).__init__()
    # python3:super().__init__()
    '''遇到多继承中出现了super关键字,如何更准确的知道它的查找顺序,我们需要打印出类的mro列表'''
    print(类名.mro())

多态

# 首先要理解什么是多态,故名思意,多态就是多种状态,不同的对象调用出同一个接口,表现出多种状态

class Animal():
    def who(self):
        print("I am an Animal")
class Duck(Animal):
    def who(self):
        print("I am a duck")

class Dog(Animal):
    def who(self):
        print("I am a dog")

class Cat(Animal):
    def who(self):
        print("I am a cat")
if __name__ == "__main__":
    duck=Duck()
    dog=Dog()
    cat=Cat()
    duck.who()
    dog.who()
    cat.who()

# 我们定义了duck,dog和cat三个对象,每个对象都实现了who()方法。你看,他们的接口名称都是相同的,他们分别调用who()方法,但有有不同的输出,不同的表现。以下是输出结果:
    I am a duck
    I am a dog
    I am a cat


# 抽象类
    '''
    	抽象类的特点:只能被继承,不能被实例化
    '''
    import abc
    class People(metaclass=abc.ABCMeta):
        @abc.abstractmethod
        def speak(self):
            pass
        
    class People():
        def speak(self):
            raise Exception('必须实现该方法')
            
    class Student(People):
        def speak(self):
            pass

鸭子类型

'''	鸭子类型:它是一种动态的编程风格,我们更多关注的是对象的行为,而不是对象的类型,我们不用在使用type或者isinstance查出它的类型了'''
class Animal():
    def who(self):
        print("I am an Animal")
class Duck(Animal):
    def who(self):
        print("I am a duck")

class Dog(Animal):
    def who(self):
        print("I am a dog")

class Cat(Animal):
    def who(self):
        print("I am a cat")

def func(obj):
    obj.who()

if __name__ == "__main__":
    duck=Duck()
    dog=Dog()
    cat=Cat()
    func(duck)
    func(dog)
    func(cat)
    
# 定义一个函数func(),这个函数对参数有一个要求,那就是参数必须有who()这个方法。不管你是什么对象,是duck对象也好,是dog对象也罢,只管对象实现who()方法就可。这就是鸭子类型,它根本不管你是什么对象,只要你有这个方法,有这个行为,表现得像鸭子,走起来像鸭子,游泳起来鸭子,叫起来也像鸭子,那么尽管你是一只会飞天的猪,也是称为鸭子类型。

魔法方法

1. __init__
2. __str__,__repr__
	"""
		1. 打印对象或者输出对象的时候,会自动触发
		2. 返回值必须是字符串,不能没有返回值
		3. 如果同时存在的时候,__str__的优先级最高
		4. 一般情况都用了__str__,偶尔也会遇到__repr__
	"""
3. __del__
	"""
		1. 删除对象的时候触发
		2. 当程序全部执行完毕的时候也会触发
		3. 一般用在回收系统资源的时候使用
	"""
4. __doc__
	# 查看类的信息
5. __enter__,__exit__
	'''
		1. 当出现with语句的时候,会触发__enter__
		2. __enter__方法执行之后,开始执行with语法的代码块
		3. 当with语句执行完毕之后,执行__exit__方法
		4. 当with代码块中出现了异常,在__exit__方法中能够得到异常的信息,(异常类型,异常值,追溯信息)
		5. 如果在__exit__方法中:return True,可以清除异常,相当于什么都没发生
	'''
6. __getattr__,__setattr__,__delattr__
	'''
		1. __getattr__:当使用句点符查找不存在的属性的时候触发
		2. __setattr__: 当使用句点符修改存在的属性值或者增加不存在的属性值得时候会自动触发
		3. __delattr__: 删除一个属性的时候,会自动触发
	'''
7. __getitem__,__setitem__,__delitem__
	"""
		1. __getitem__:当通过中括号取值的时候,会自动触发
		2. __setitem__: 当通过中括号改值的时候,会自动触发
		3. __delitem__: 当通过中括号删除值得时候,会自动触发
	"""
8. __call__
	"""
		当给对象加括号调用的时候会自动触发!!!
	"""

反射

# 通过字符串来操作对象的属性
1. getattr(stu, 'name',666)
	"""
		1. 如果第二个参数是属性的话,直接返回属性的值
		2. 如果属性不存在,会报错
		3. 如果写了第三个参数,当属性不存在的时候,会把第三个值返回
		4. 如果第二个参数是函数名的话,返回的是函数的内存地址,如果想调用,直接返回的结果加括号
	"""
2. setattr(stu, 'x', '666')
	
3. delattr(stu, 'x')
4. hasattr(stu, 'x')
补充:
	1. 以上4个方法中得第一个参数也可以写模块名
    	import time
    	time.sleep(3)
    
   	    sleep=getattr(time, 'sleep')
        sleep(3)
  	2. __import__
    # 通过字符串的形式导入模块
    time=__import__('time')
    time.sleep()

异常

1. 主动抛出异常
	# 关键字是:raise
    raise Exception('')
    raise TypeError('')
    raise IndexError('')
    raise KeyError('')
'''父类限制子类的行为:'''
class Animal():
    def speak(self):
        raise Exception('必须实现speak方法')
class People(Animal):
    def speak(self):
        pass

obj = People()
obj.speak()
2. 自定义异常
	# 1. 先写一个自定义类,
    # 2. 继承BaseException
    # 3. raise 抛出异常
3. 断言
	assert 表达式
    '''表达式的条件一定是True,否则直接报错'''
	...
    d = {'token':'dasdasdasdasdasdasdsad'}
    assert 'token' in d
posted @ 2023-05-17 20:00  秋洛尘  阅读(31)  评论(0)    收藏  举报