1. 本质
一切皆对象
2. 类
1. 概念
类是抽象的概念,它是对具有相同属性和方法的对象的一个通称。
2. 语法
class[关键字,不可省略] 类名:
属性定义[例如: age=0]
方法定义[例如: 构造函数]
# 调用类
例如: a=a(); # 实例化类
a.age=19 # 并且给属性赋值
3. 对象
对象是类的实例
1. 对象的内容
对象有其属性和方法。
例如对象为人:
属性:姓名、年龄、身高等固有的特性
方法:吃、阅读、学习等为达到某种目的的行为。
2. 类和对象的区别
类是抽象概念,对象是具体的。类是一个模板,而对象就是根据这个模板创造出来的东西。
比如,创建一个学生类,实例化一个学生小白,那么小白就是学生类中的一个对象。可以通过类实例化一个个的对象,每个对象都拥有相同的方法,但各自的数据可能不相同,它们之间互相独立,互不影响。
注意:一个类可以实例化出多个对象,但是每个对象都不一样,都是全新的独立个体
4. 类和对象
1. 定义一个学生类
# ① 定义一个类
class Student:
name = "小宝"
sex = "男"
def fun(self): # 类方法必须包含参数 self, 且为第一个参 数,self 代表的是类的实例
print("姓名:"+self.name+",性别:"+self.sex)
# ② 通过类实例化对象
stu = Student() # 实例化一个对象,名为stu
stu.name = "宝宝" # 修改name属性内容
# ③ 调用方法
stu.fun()
# ④ 一个类可以实例化出多个对象,这里的stu和stu2不是同一个对象
stu2 = Student()
stu2.fun()
输出结果如下:
我们可以看到输出的内容不一样,因为修改的name是stu对象的。我们实例化出来的这两个对象,它们的方法是相同的,但各自输出的数据不一样,是因为它们分别是一个独立的个体,谁也不影响谁。
2. 构造函数
构造函数:在创建对象的同时,可以直接修改对象内部属性的值。(不用像第一个例子需要好几行代码才可以将对象值修改。)
class Student:
name = "小宝"
sex = "男"
# 构造函数
def __init__(self,a,h):
self.name = a
self.sex = h
def fun(self): # 类方法必须包含参数 self, 且为第一个参 数,self 代表的是类的实例
print("姓名:"+self.name+",性别:"+self.sex)
stu = Student("宝宝", "女")
stu.fun()
注意:
1. _ init_() 方法,该方法被称为构造方法,开头和结尾各有 2 个下划线,并且中间不能有空格
2. self 必须作为第一个参数
3. 在创建一个对象时默认被调用,不需要手动调用
4. init() 方法可以有参数,可以通过传参数,对不同的对象设置不同的初始化属性,参数通过 init() 传递到类的实例化操作上
3. self
指调用self所在方法的对象。
#① 定义一个类
class Student:
def fun(self): # 类方法必须包含参数 self, 且为第一个参 数,self 代表的是类的实例
print('这是fun1')
self.fun2()
def fun2(self):
print('这是fun2')
# ② 通过类实例化对象
stu = Student()
# ③ 调用
stu.fun()
4. 创建多个对象时,self地址是否一样?
# ① 定义一个类
class Student:
def fun(self): # 类方法必须包含参数 self, 且为第一个参 数,self 代表的是类的实例
print('这是fun1')
print(self)
# ② 通过类实例化对象stu1 并调用
stu = Student()
stu.fun()
# ③ 通过类实例化对象stu2 并调用
stu2 = Student()
stu2.fun()
答案是不相同的。注意前面的类和对象的概念和区别。
5. __str__方法
如果使用print打印对象时,默认会打印对象的内存地址,有没有什么方法打印其它内容?
答案:定义__str__方法,将会打印这个函数return的内容。
class Student:
# 构造函数
def __init__(self):
self.name = '小白'
def __str__(self):
return "123"
stu = Student()
print(stu)
6. del
删除对象时,python解释器会默认调用它。
class Student:
# 构造函数
def __init__(self):
self.name = '小白'
def __del__(self):
print('123')
stu = Student()
5. 类的属性
静态变量
实例变量
局部变量: 在函数内部定义的属性,并且没有以self为前缀。比如:变量名 = 值
1. 静态属性(类属性)
类变量是指在类中,在各个方法外的定义变量,它被所有的类对象所共有,并且在内存中只存在一个副本
class Student:
# 类变量:name和sex
name = "小宝"
sex = "男"
def fun(self):
print("姓名:"+self.name+",性别:"+self.sex)
print(Student.name) # 类名直接打点访问
stu = Student()
print(stu.name) # 类的实例打点调用
修改类变量,会影响到所有的实例化对象
class Student:
# 类变量:name和sex
name = "小宝"
sex = "男"
# 修改前
print("修改前类变量:"+Student.name)
# 修改
Student.name = "宝宝"
#修改后
print("修改后类变量:"+Student.name)
stu = Student()
stu2 = Student()
stu3 = Student()
print("修改后类对象stu:"+stu.name)
print("修改后类对象stu2:"+stu2.name)
print("修改后类对象stu3:"+stu3.name)
如果要修改类属性,只能通过类修改,如果使用对象去修改,相当于在类外面添加了一个实例属性
class Student:
# 类变量:name和sex
name = "小宝"
sex = "男"
# 1.创建对象
stu = Student()
# 2.通过对象修改name
stu.name = '小黑'
# 3. 分别用类和对象打印name
print(Student.name) # 小宝
print(stu.name) # 小黑
注意:
- 类变量被所有类对象共有,通过类名修改类变量的值,会影响所有的实例化对象
- 通过类对象是无法修改类变量的。通过类对象对类变量赋值,其本质将不再是修改类变量的值,而是在给该对象定义新的实例变量
- 类变量我们自己也可以进行一个添加,比如:Student.Id = 1
- 如果要修改类属性,只能通过类修改,如果使用对象去修改,相当于在类外面添加了一个实例属性,如第三条
2. 实例属性
- 实例属性: 对象属性,以 self 为前缀的属性。比如:self.变量名
class Student:
# 构造函数
def __init__(self,a,h):
self.name = a # name、sex 都是实例属性
self.sex = h
def fun(self):
print("姓名:"+self.name+",性别:"+self.sex)
- 实例对象修改和添加,实例化出来的对象它们都是一个独立的个体,因为它每创建一个对象时就会单独存储一份
class Student:
# 构造函数
def __init__(self,a,h):
self.name = a # name、sex 都是实例属性
self.sex = h
# ① 创建stu对象 并修改和添加属性
stu = Student("小白","男")
stu.sex = "女" # 修改
stu.age = 20 # 添加
# ② 创建stu2和stu3对象
stu2 = Student("小蓝","男")
stu3 = Student("小蓝","男")
# ③ 分别调用三个对象的sex
print(stu.sex) # 输出女
print(stu2.sex) # 输出男
print(stu3.sex) # 输出男
# ④ 分别调用三个对象的age
print(stu.age) # 输出20
print(stu2.age) # 报错
print(stu3.age) # 报错
- 类可以去访问类属性,但是不可以访问实例属性,对象打点都可以访问。
class Student:
a = 10
# 构造函数
def __init__(self,a,h):
self.name = a # name、sex 都是实例属性
self.sex = h
# 创建对象
stu = Student('小小','男')
# 1.访问类属性:用类和对象
print(Student.a)
print(stu.a)
# 2.访问实例属性:类和对象
# print(Student.name) # 会报错
print(stu.name)
3. 私有属性
- __a:属性前加两个下划线,可以在类里面使用
class Person:
def __init__(self):
self.name = '我是Person'
self.__a = '我是私有属性'
def a(self):
print(f"{self.name}方法")
e = Person()
print(e.name)
print(e.a)
- 利用函数修改私有属性
class Person:
def __init__(self):
self.__a = '我是私有属性'
def aaa(self):
print("修改前:",self.__a)
def aa(self,x):
self.__a=x
print("修改后:",self.__a)
# ① 实例化对象
e = Person()
# ② 修改前
e.aaa()
# ③ 修改后
e.aa("我被修改了")
6. 类的方法
1. 实例方法
class Student:
# 构造方法属于实例方法
def __init__(self):
self.name = "小白"
# 定义一个sayHi实例方法
def sayHi(self):
print("这是Sudent中say实例方法")
# 实例化名为stu的对象
stu = Student()
stu.sayHi() # 通过实例化的方式 对象名打点调用
Student.sayHi(stu) # 使用类名调用实例方法时,需要手动给 self 参数传值
2. 静态方法 (@staticmethod )
class Student:
# 静态方法
@staticmethod
def fun():
print("这是静态方法")
stu = Student()
stu.fun() # 对象名打点调用静态方法
Student.fun() # #类名打点调用静态方法
3. 类方法 (@classmethod)
class Student:
# 类方法
@classmethod
def fun2(cls):
print("这是类方法")
Student.fun2() # 调用
class Student:
# 类方法
@classmethod
def fun2(cls):# cls 类对象的引用
print('cls:',cls)
print("这是类方法")
stu = Student()
stu.fun2()
print('stu:',stu)
print('Student:',Student)
注意:
1.通过实例定义的变量只能被实例方法访问
2.在类中定义的静态变量可以被实例方法,被静态方法和类方法访问
3.实例方法不能被静态方法和类方法访问,但静态方法和类方法可以被实例方法访问
4. 私有方法
方法名前加两个下划线
# 子类调用父类的同名属性和方法
class Person:
def __init__(self):
self.name = '我是Person'
self.__B = '我是私有属性'
def a(self):
print(f"{self.name}方法")
def __B(self):
print("我是私有方法")
e = Person()
print(e.name)
print(e.a)
e.a()
e.B() # Attri buteError:’ Person’ object has no attribute’ B’
AttributeError:‘Person’对象没有属性‘B’
7. 继承
1. 单继承
实现继承的类称为子类(派生类名),被继承的类称为父类(基类名)
class 派生类名(基类名)
属性
方法
class Person:
name1 = '我是父'
def a(self):
print("我是父方法")
class Emp(Person):
name2 = "我是子"
def b(self):
print("我是子方法")
e = Emp()
# 调用父类
print(e.name1)
e.a()
2. 多继承
class Person:
name = '我是Person'
def a(self):
print("我是Person方法")
class Person2:
name1 = '我是Person2'
def a(self):
print("我是Person2方法")
class Emp(Person,Person2):
name2 = "我是子"
def b(self):
print("我是子方法")
e = Emp()
print(e.name)
print(e.name1)
e.a()
注意:在多继承中,如果一个类有多个父类的话,会优先去继承第一个父类的同名属性和方法。
3. 重写
1. 子父类拥有同名的属性和方法时
如果子类和父类拥有同名的属性和方法时,子类创建对象去调用属性和方法,调用到的是子类的属性和方法
class Person:
name = '我是Person'
def a(self):
print("我是Person方法")
class Person2:
name = '我是Person2'
def a(self):
print("我是Person2方法")
class Emp(Person,Person2):
name = "我是子"
def a(self):
print("我是子方法")
e = Emp()
print(e.name)
e.a()
2. 子类调用父类的同名属性和方法
class Person:
def __init__(self):
self.name = '我是Person'
def a(self):
print("我是Person方法")
class Emp(Person):
def __init__(self):
self.name = "我是子"
def a(self):
print("我是子方法")
def b(self):
Person.__init__(self)
# print(self)
Person.a(self)
e = Emp()
#print(e)
e.b()
3. super()
子类调用父类的同名属性和方法,例2的另外一种写法
# 子类调用父类的同名属性和方法
class Person:
def __init__(self):
self.name = '我是Person'
def a(self):
print(f"{self.name}方法")
class Emp(Person):
def __init__(self):
self.name = "我是子"
def a(self):
print("我是子方法")
def x(self):
super(Emp,self).__init__()
super(Emp,self).a()
e = Emp()
e.x()
# 子类调用父类的同名属性和方法
class Person:
def __init__(self):
self.name = '我是Person'
def a(self):
print(f"{self.name}方法")
class Person2(Person):
def __init__(self):
self.name = '我是Person2'
def a(self):
print(f"{self.name}方法")
super(Person2,self).__init__()
super(Person2,self).a()
class Emp(Person2):
def __init__(self):
self.name = "我是子"
def a(self):
print("我是子方法")
# super()
def x(self):
super(Emp,self).__init__()
super(Emp,self).a()
e = Emp()
e.x()
4. super() 无参
# 子类调用父类的同名属性和方法
class Person:
def __init__(self):
self.name = '我是Person'
def a(self):
print(f"{self.name}方法")
class Emp(Person):
def __init__(self):
self.name = "我是子"
def a(self):
print("我是子方法")
# super() 无参
def x(self):
super().__init__()
super().a()
e = Emp()
e.x()
4. __mro __
可以用来查看类的继承关系
class Person:
name = '我是Person'
def a(self):
print("我是Person方法")
class Person2:
name = '我是Person2'
def a(self):
print("我是Person2方法")
class Emp(Person,Person2):
name = "我是子"
def a(self):
print("我是子方法")
e = Emp()
print(Emp.__mro__)