python之面向对象


面向对象

  • 本质:将特定的数据与特定的功能绑定到一起 将来只能彼此相互使用
    • 对象其实就是一个容器 里面将数据和功能绑定到一起

使用场景一:

​ eg:游戏人物……

​ 只负责创造出该人物具备的功能 至于后续战绩如何无人知晓 不是面向对象关心的内容

区别

  • 面向过程编程相当于让你给出一个问题的具体解决方案
  • 面向对象编程相当于让你创造出一些事物之后不用你管

对象与类的概念

对象:数据与功能的接合体
类:多个对象相同的数据和功能的接合体
'''
类比学习法: 一个人	可以看成对象
		   多个人	人类
'''
类:主要用于记录多个对象相同的数据和功能
对象:则用于记录多个对象不同的数据和功能
PS:在面向对象编程中 类主要是为了节省代码 对象才是核心

对象与类的创建

在编程世界里先有类才有对象

创建类的完整语法
#学生类
class person:
1.class是定义类的关键字
2.person是类的名字
	类名的命名跟变量名一致 并且推荐首字母大写(为了更好的区分)
3.类体代码
	公共的数据/公共的方法   
    
4.通过类名加括号可以实例化一个对象

5.我们习惯将类或者对象聚点符后面的东西称为属性或者方法

对象独有的数据

class Student:
    school = "清华大学"#属性
    
    def choice_course(self):#对象具有的方法
        print("正在上课")
        
obj1 = Student()#实例化出 一个对象
'''
类体最常见的是变量的定义和函数的定义,但其实类体可以包含任意Python代码,类体的代码在类定义阶段就会执行,因而会产生新的名称空间用来存放类中定义的名字,可以打印
Student.__dict__
来查看类这个容器内盛放的东西
'''
    
class Student:  
    school='清华大学' 
    
    #__init__该方法会在对象产生之后自动执行,专门为对象进行初始化操作,可以有任意代码,但一定不能返回非None的值  
def __init__(self,name,sex,age):      
    self.name=name     
    self.sex=sex       
    self.age=age   
    
def choose(self):        
	print('%s is choosing a course' %self.name)
    
#实例化出一个对象
stu1 = student('jason','male','eighteen')
print(stu1.__dict__)

对象独有的方法/功能

class person:
    h_type = "人类" #多个对象公共的数据
    
    def __init__(self,name):#让对像拥有独有的数据
        self.name = name
        
    def eat(self):#对象独有方法,只针对对象
        print("正在干饭")

动静态方法

专门针对在类体代码中编写的代码
1.绑定给对象的方法
	直接在类体代码中编写即可
    	对象调用直接将对象当做第一个参数传入
       类调用则有几个形参就传几个形参
class Student:
    school = "清华大学"
    
    def run(self): #绑定给对象的方法self用于接收对象
        print("互动课堂",self)
    
    @classmethod
    def eat(cls): #绑定给类的方法cls用于接收类
        print("清华讲堂",cls)
        
    @staticmethod #静态方法
    def sleep(a,b):#无论谁来调都必须按照不同函数的方式调用
        print("现代化设备")        
        
stu1 = Student()
#调用绑定给类的方法
student.eat()#绑定给类的方法类调用自动将类当做第一个对象传入

stu1.eat() #对象调用类方法会将产生该对象的类当成第一个参数传入
 
#类和对象调用静态方法都必须传入相对应的参数没有默认参数    
Student.sleep(1,3)
stu1.sleep(1,4)

面向对象三大特性

'''
面向对象的三大特性
	封装、继承、多态
'''
1.继承的含义
	表示类与类之间数据之间的关系
    
2.继承的目的
	减少代码的编写
    
3.继承的操作
class Father:
	money =999
    
    def run(self):
        print("继承财产")

#1.定义类名的时候在类名后加括号
#2.括号里面填写需要继承的类名
'''
我们将被继承的类称为:父类、基类、或超类;
	进行继承的类称为:子类、派生类;
'''
class Son(Father1,Father2,Father3):
	pass

print(son.money)
print(son.run())

4.继承的本质
	抽象:将多个类共有的数据或功能抽取出来行程一个基类
	继承:从上往下继承父类里面的数据和资源
'''
对象:数据和功能的接合体
类:多个对象,相同的数据和功能的接合体
父类:多个类,相同的数据和功能的结合体

'''

名字的查找顺序

1、不继承的情况下名字的查找顺序
	先从对象自身查找 没有的话 再去产生该对象的类中查找

2、单继承的情况下名字的查找顺序
	先从对象自身查找 然后是产生该对象的类 然后是一个个父类

3、多继承的情况下名字的查找顺序
  • 1、不继承的情况下名字的查找顺序
class Student:
    school = '清华大学'
    def choice_course(self):
        print("正在上课")
        
stu1 = student()
print(stu1.school)
stu1.school = '北京大学' #在自己命名空间中产生了新的school,不会更改类中的数据
print(stu1.school)#北京大学
print(Student.school)#清华大学

  • 2、单继承的情况下名字的查找顺序


    主要涉及对象的查找名字 那么几乎是

    ​ 对象本身> 类 >父类


    class A:
        name = 'from A'
        
    class B(A):
        name = 'feom B'
    
    class C(B):
        name ='from C'
        
    calss myclass(C):
        name =  'from myclass'
    obj = myclass()
    print(obj.name)
    
    
  • 3、多继承的情况下名字的查找顺序

    • 非菱形继承> 最后不会归总到一个类上> 深度优先
    • 菱形继承> 最后都归总到一个类上> 广度优先
    • 通过(类.mro)方法查看该类产生的对象名字的查找顺序
class A:
	name = 'from A'
class B:
    name = 'from B'
class C:
    name = 'from C'
class MyClass(A,B,C):#查找顺序A>B>C
    name = 'from MyClass'
obj = MyClass()
print(obj.name)

经典类与新式类(object)

金典类
	不继承objict或其子类的类(什么都不继承)
 新式类
	继承了object或其子类的类
'''
在python3中所有的类都默认继承object类
在python2中不写object就是经典类
以后再定义类的时候如果没有要继承的类就继承object 可以更好的兼容python2
'''    

派生方法

  • 子类中定义了与父类一模一样的方法并且做了扩充就叫派生
class Person(object):
    def __init__(self,name,age)
    	self.name = name
    	self.age = age
        
class Teacher(person):
    def __init__(self,name,age,level):#子类需要的属性父类不满足时
        '''
        # person.__init__(self,name,age)  先调用父类的方法
        # self.level = level	#再自己补充一些
        '''
        super().__init__(name,age,gender) #super专门用于子类调用父类的方法
        self.level = level	#再自己补充一些
class Student(Person):
    pass

派生实战演练

问题:json可以序列化的类型只有基本类型
#解决方式1:手动将不符合要求的数据转化成符合要求的
import datetimee
ipmort json
d = {"t1":str(datetime.datetime.today()),
     "t2":str(datetime.date.today())
	}# 获取当前时间
res = json.dump(d)#序列化字典
print(res)

#解决方式2:利用派生方法
d = {"t1":str(datetime.datetime.today()),
     "t2":str(datetime.date.today())
	}# 获取当前时间
res = json.dump(d)#序列化字典
print(res)

image-20220828201116596

三大特性之封装


  • 在类的定义阶段中使用‘__’开头的属性默认都是隐藏的属性 后续类和对象都无法访问

  • 在python中不会真正限制代码的访问 隐藏的代码要访问需要做相应的变形

    __变量名 会变成:_类名__变量名

封装其实是将数据或者功能隐藏起来(包起来 装起来)
隐藏的目的不是让用户无法使用 而是给这些隐藏的数据开设特定的窗口 让用户使用接口才可以去使用 我们在接口中添加一系列额外的操作
class Person:
    d_type = '人类'
    __school = '清华大学'
    __name = 'jason'
    __age = eight
    def get_info(self):
        return f"{self.__school},{self.__name}"
    def eat(self):
        print('立德立言')
        
obj1 = person()
print(obj1.get_info())#通过定义的类方法访问信息

property伪装属性

可以简单的理解为 将方法伪装成数据
	obj.name	 #数据只需要.数据名就可以调用
    obj.func()	  #方法需要加括号才能调用
伪装之后可以将func方法伪装成数据 obj.func    

#计算人体的MBI指数
class person:
    def __init__(self,name,weight,height)
    	self.name = name
    	self.weight = weight
    	self.height = height
    @property
    def MBI(self):
		return self.weight/(self.height**2)
P1 = Person("jason",88,1.85)
res = P1.MBI()
print(P1.MBI)#不加括号也可以直接调用

面向对象之反射

  • 反射:通过字符串来操作对象的数据或方法
    • 反射就四个方法:hasattr、getattr、setattr、delattr

什么时候使用反射:只要在需求中看到了、‘关键字’、‘对象’、‘字符串’就用反射的知识


hasattr():判断对象是否含有某个字符串对应的属性
getattr():获取对象字符串对应的属性
setattr():根据字符串给对象设置属性
delattr():根据字符串给对象删除属性

class Student(object):
    school = '清华大学'
    
    def choice_course(self):
        print("选课")
        
stu = Student()
#需求:判断用户提供的名字在不在对象可以使用的范围内
#方式1:利用异常捕获
try:
    if stu.school:
        print(f"True{stu.school}")
    except Exception:
    	print("没有改属性")
#方式2:获取用户输入的名字 然后判断该名字有没有
target_name = input().strip()#用户输入的是字符串
'''上面的异常捕获不好实现 需要用反射'''
print(hasattr(stu,target_name))
getattr(stu,target_name)
setattr(stu,'gender','male')#用户自己输入设置属性
delattr(stu,'age')#用户自己输入需要删除的属性

面向对象魔法方法

  • 魔法方法其实就是类中定义的双下方法 之所以叫魔法方法是因为这些方法达到条件后自动触发
    • eg:“–init–“方法在给对象设置独有数据的时候自动触发(实例化)
class Myclass(object):
    def __init__(self):#实例化对象的时候自动触发
        print("__init__方法")
        
    def __str__(self):#当对象被执行打印的时候自动触发 该方法必须返回一个字符串
        print("__str__方法")
        return "对象:%s"%self
    
    def __call__(self,*args,**kwargs):#对象加括号自动调动该功能
        print("__call__方法")
        print(args)
        print(kwargs)
        
    def __getattr__(self,item):#当对象获取一个不存在的属性名自调用该方法返回什么 								对象 获取不存在的属性名就会得到什么  型参item								就是	想要获取的不存在的属性名 当类中也有                                        __getattribute__时不走此代码 
        print("__getattr__方法")
        return 123
        
     def __setattr__(self,key,value):#对象添加属性值得时候自动触发  对象.属性名 										= "属性值"
        print("__setattr__方法")
        print(key)
        print(value)
        
     def __del__(self):#对象在被删除的时候自动触发
        print("__del__方法")
        
     def __getattribute__(self,item):#对象获取属性的时候触发 无论属性存不存在 当									类中也有__getattr__时不走
       print("__grtattribute__方法")
       return super(MYclass,self).__getattribut__(item)
    
    def __enter__(self):#对象被with语法执行时自动触发 该方法返回什么 as关键字后变量名就得到什么
        print("__entrt__方法")
        return 123
    
    def __exit__(self,exc_type,exc_val,exc_tb):#对象被with语法执行并运行完with子代码后 自动触发
		print("__exit__方法")
        
obj = Myclass() 
obj(1,2,name='jason',age = '18')
print(obj.age)#获取对象不存在的属性名age
with obj as f:
print(f)

元类简介

class Mycalss(object):
    psss
obj = Myclass()
print(type(obj))#查看产生对象obj的类:<class '__main__.Myclass'>
print(type(Myclass))#查看产生对象Myclass的类:<class 'type'>
'''
通过推导我们得出 自定义的类都是有 type类得出的  产生类的类称为 “元类”
'''

产生类的两种方式

1.class 关键字
	class Myclass:
    	pass
    
2.利用元类type
	type(类名,类的父类,类的名称空间)
	

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/283022.html

(0)
上一篇 2022年8月30日
下一篇 2022年8月30日

相关推荐

发表回复

登录后才能评论