将数据与功能绑定到一起的操作起名为面向对象编程,将特定的数据与特定的功能绑定到一起 将来只能彼此相互使用。
面向对象中'对象'其实就是一个容器,里面将数据和功能绑定到了一起
只负责创造人物功能后续的具体实现什么结果就不需要负责:游戏人物开发
对象:数据与功能的结合体,记录多个对象不同的数据和功能
类:多个对象相同的数据和功能体的结合,记录多个对象相同的数据和功能
ps:类主要用于记录多个对象相同的数据和功能,对象主要记录多个对象不同的数据和功能
class People: name = 'aaa' # 公共的数据与方法 ''' class:定义类的关键字 People类的名字(为了更好的区分推荐首字母大写跟变量名一致) 类体代码公共的数据与方法(在定义阶段执行)''' '''查看名称空间的方法''' People.__dict__ # 该方法可以查看名称空间可以看成是一个字典(字典取值) '''获取名称空间的方法:句点符 类实例化产生对象:类名加括号 obj = People() print(obj.name) obj.name = 'bb' 修改值 ''' '''将添加独有的数据封装成函数:__init__创建独有的数据''' def __init__(self, name, age, gender): self.name = name # obj.__dict__['name'] = name self.age = age # obj.__dict__['age'] = age self.gender = gender # obj.__dict__['gender'] = gender无法直接定义对象独有的方法python解释器针对这个问题添加了非常牛的特性:
定义在类中的函数默认是绑定给对象(相当于是对象独有的方法)
class Person: type = '人类 def __init__(self, name): # 让对象拥有独有的数据 self.name = name def eat(self): # 是多个对象公共的方法 也算多个对象独有的方法 对象来调用就会将对象当做第一个参数传入 print('%s正在干饭'%self.name) obj = Person('aa') print(obj.eat())动静态方法:
1.绑定给对象的方法
直接在类体代码中编写即可
对象调用会自动将对象当做第一个参数传入
类调用则有几个形参就传几个实参
2.绑定给类的方法
3.静态方法(普普通通的函数)
class Student: school = '清华大学' # 绑定给对象的方法 def run(self): # self用于接收对象 print('run', self) @classmethod # 绑定给类的方法 def eat(cls): # cls用于接收类 print('eat', cls) @staticmethod # 静态方法 def sleep(a, b): # 无论谁来调用都必须按照普普通通的函数传参方式 print('sleep') stu1 = Student() # 调用绑定给类的方法 Student.eat() # 类调用会自动将类当做第一个参数传入 eat(Student) stu1.eat() # 对象调用会自动将产生该对象的类当做第一个参数传入 eat(Student) # 调用静态方法 Student.sleep(1,2) stu1.sleep(1, 2)
1.继承的简介
继承就是让类继承了另一个类转变为父子关系,子类可以直接访问(调用)父类的静态属性和方法。在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类。可以减少代码编写、减少代码冗余、提高重复使用率
2.继承的操作
class 类名(父类名): pass ''' 定义类的时候类名后面加括号 括号内填写你需要继承的类名 括号内可以填写多个父类用逗号隔开'''3.继承的本质
1.抽象:把多个类公共的数据或功能拿出来形成一个基类
2.继承:从上往下获取每个基类里的资源
3.对象:数据和功能的结合体
4.类:多个对象相同的数据和功能的结合体
5.父类:多个类相同的数据和功能的结合体
1.封装的含义
封装其实就是指隐藏对象的数据和功能,隐藏的数据开设特定的接口用户需要使用接口才可以使用,能够提高程序安全性。 __类名__变量名 __变量名
2.property伪装属性
property可以简单的理解为把方法伪装成数据
class Person: def __init__(self,chinese,mathematics,English): self.chinese = chinese self.mathematics = mathematics self.english = English @property def average_value(self): return (self.chinese+self.mathematics+self.english)/3 obj = Person(88,90,59) print(obj.average_value) # 不需要写括号 '''打印结果 79.0 '''
1.多态的含义:
一种事物的多种不同形态,比如衣服它可以是长袖、短袖、衬衫、卫衣等等不同的形态但都有衣服的固定功能。所以当代码中有公共的功能时我们可以定义成一个固定的功能无论哪个要用直接调用即可。
2.代码举例:
class Clothes(object) def ornament(self): pass class Short_sleeves(Clothes) def ornament(self): print('今天穿短袖') class Sweatshirt(Clothes) def ornament(self): print('今天穿卫衣') class Dress(Clothes) def ornament(self): print('今天穿裙子') s1 = Short_sleeves() s2 = Sweatshirt() s3 = Dress() s1.ornament() '''今天穿短袖''' s2.ornament() '''今天穿卫衣''' s3.ornament() '''今天穿裙子'''
1.名字查找顺序:
没有继承父类 :对象自身 >>> 类
单继承 :对象自身 >>> 类 >>>继承的父类
2.多继承的情况下名字查找顺序:
菱形继承:A >>> B C >>> D >>> E
非菱形继承:A >>> B C >>> D
1.python2解释器
在python2中有经典类和新式类,可以继承object或其子类的类也可以什么都不继承
2.python3解释器
在python3中所有的类默认都会继承object,只有新式类。
1.什么是派生:
派生方法通俗讲就是当运行模块函数时可以在途中进行拦截然后添加自己需要添加的操作然后再返回继续执行原本的模块函数。
2.具体操作:
先拦截dumps然后观察源代码自己创一个类让其中途运行自己写的然后再返回dumps源代码继续执行。
import datetime import json d = { 't1': datetime.datetime.today(), 't2': datetime.date.today()} '''通过查看dumps源码进行改动''' class MyJsonEncode(json.JSONEncoder): def default(self, data): '''data就是json即将要序列化的数据''' if isinstance(data, datetime.datetime): return data.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(data, datetime.date): return data.strftime('%Y-%m-%d') '''如果是可以序列化的类型 那么不做任何处理 直接让它序列化即可''' return super().default(data) res = json.dumps(d, cls=MyJsonEncode) print(res) json.dumps(d, cls=MyJsonEncode)
1.反射的含义:
用字符串的方式操作对象的数据或方法,例如用户想判断对象中是否有某个变量名时因为input获取的是字符串所以可以用反射来处理。当看到需求中有字符串和对象时可以肯定需要用反射来操作。
2.反射主要的方法:
hasattr():判断一个对象中是否有某个字符串对应的属性
getattr():获取对象字符串对应的属性 (一般 hasattr 和 getattr 结合使用)
setattr():根据字符串给对象设置属性
delattr():根据字符串给对象删除属性
3.代码举例:
'''hasattr 和 getattr 结合使用''' class Person: type = '是个人' def profile(self): print('小胖子') obj = Person() while True: target_name = input('请输入你要查找的名字>>>:').strip() if hasattr(obj, target_name): print(getattr(obj, target_name)) else: print('对不起,没找到你要的对象') '''打印结果 请输入你要查找的名字>>>:type 是个人 请输入你要查找的名字>>>:profile> '''
class Person: type = '是个人' def profile(self): print('小胖子') obj = Person() setattr(obj,'name','aa') # 对象没有这个属性则添加属性 setattr(obj,'age',18) # 对象没有这个属性则添加属性 print(obj.age) delattr(obj,'name') # 删除对象内的属性 print(obj.__dict__) '''打印结果 18 {'age': 18} '''
1.魔法方法的含义
在类中会定义好的名字是“__xx__”格式的再进行相对应的操作时会自动被调用的方法被称为魔法方法
2.常见的魔法方法
__init__ : 实例化对象的时候自动触发,初始化一个类,在创建实例对象为其赋值
__call__ : 当对象加括号调用时自动触发该方法
__str__ : 对象被执行打印操作的时候会自动触发,该方法必须返回一个字符串
__getattr__ : 当对象获取的属性名不存在时触发,返回获取的这个不存在的属性名
__setattr__ : 对象操作属性值的时候自动触发
__del__ : 对象在被主动或被动删除的时候自动触发
__getattribute__ :对象在获取属性的时候自动触发 不管这个属性是否存在
__exit__ :对象被with语法执行并运行完with子代码之后自动触发
__exit__(self, exc_type, exc_val, exc_tb): 对象被with语法执行并运行完with子代
码之后 自动触发'''
__enter__(self): 对象被with语法执行的时候自动触发 该方法返回什么 as关键字后面的变量名就能得到什么
1.元类的含义
过class关键字定义的类本质也是对象,对象又是通过调用类得到的, lass关键字定义的类肯定也是调用了一个类得到的(type类),这个类就是
元类
2.创建方式
class 关键字
class Person: passtype 关键字(类名、父类、类的名称空间)
class Person(type): pass """只有继承了type的类才可以称之为是元类""" class MyClass(metaclass=Person): pass """如果想要切换产生类的元类不能使用继承 必须使用关键字metaclass声明"""类中的__init__用于实例化对象
元类中__init__用于实例化类3.元类操作对象与类的产生过程
1.对象加括号执行产生该对象类里面的双下call
2.类加括号执行产生该类的元类里面的双下call
class MyMetaClass(type): def __call__(self, *args, **kwargs): print('__call__') if args: raise Exception('必须用关键字参数传参') super().__call__(*args, **kwargs) class MyClass(metaclass=MyMetaClass): def __init__(self, name, age): self.name = name self.age = age print('__init__') obj = MyClass('aa', 88) # 当参数没有用关键字传参的时候会报错4.元类的new方法
class Person(object): def __init(self,*args,**kwargs): print('init') def __new__(cls,*args,**kwargs): print('new') print(type(cls)) obj = Person() '''打印结果 new '''__new__:专门用于产生空对象
__init__ : 专门用于给对象添加属性
ps:创建类的一个实例时,如果该类具有__new__方法,会先调用__new__方法,__new__方法接受当前正在实例化的类作为第一个参数,这个参数的类型是type。