"""
类:可以理解是一个模板,通过它可以创建出无数个具体实例
对象:类并不能直接使用,通过类创建出的实例(又称对象)才能使用。比如汽车图纸(类)和汽车(对象)的关系
属性:类中的所有变量称为属性
方法:类中的所有函数通常称为方法,和函数所有不同的是,类方法至少要包含一个 self参数
类的使用顺序:1.创建(定义)类,也就是制作图纸的过程;
2.创建类的实例对象(根据图纸造出实际的物品),通过实例对象实现特定的功能
"""
# 类的创建需要使用 class 关键字
# 基本语法格式:class 类名:
# 多个(≥0)类属性...
# 多个(≥0)类方法...
class MyClass:
x = 7
print(MyClass)
# 创建类对象的过程,又称之为类的实例化,所以也可以称之为实例对象,后续类对象都称为实例对象
# 基本语法格式: 类名(参数)
p1 = MyClass()
print(p1.x)
# __init()类构造方法
# 语法格式:
# def __init__(self,...):
# 代码块
# __init__() 方法可以包含多个参数,但必须包含一个名为 self 的参数,且必须作为第一个参数
# 所有类都有一个名为 __init__() 的函数,它始终在启动类时执行。
# 使用 __init__() 函数将值赋给对象属性,或者在创建对象时需要执行的其他操作
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person("Bill", 63)
print(p1.name)
print(p1.age)
# 在定义类的过程中,无论是显式创建类的构造方法,还是向类中添加实例方法,都要求将 self 参数作为方法的第一个参数
# self 参数是对类的当前实例的引用,用于访问属于该类的变量。
# 它不必被命名为 self,您可以随意调用它,但它必须是类中任意函数的首个参数
# 进行实例化时最好第一个参数命名为self
class Person:
def __init__(self):
print("正在执行构造方法")
# 定义一个say()实例方法
def say(self,name):
print(name,"正在学Python")
# 类变量和实例变量(类属性和实例属性)
# 类体中、所有函数之外:此范围定义的变量,称为类属性或类变量;
# 类体中,所有函数内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量;
# 类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量
# 类变量:在类中,但在各个类方法外定义的变量
class Person:
name = "you" # 定义类变量
age = "20"
def say(self, content): # 定义say实例方法
print(content)
# name 和 age 属于类变量
# 类变量的特点:所有类的实例化对象都同时共享类变量,类变量在所有实例化对象中是作为公用资源存在的
# 类方法的调用方式:使用类名直接调用,使用类的实例化对象调用
print(Person.name) #使用类名直接调用
Person.name = "youcanwill" #修改类变量的值
print(Person.name)
# 类名不仅可以调用类变量,也可以修改值
# 类变量为所有实例化对象共有,通过类名修改类变量的值,会影响所有的实例化对象
# 实例变量:在任意类方法内部,以“self.变量名”的方式定义的变量
# 只作用于调用方法的对象,实例变量只能通过对象名访问,无法通过类名访问
class Person:
def __init__(self):
self.name = "you"
self.age = "20"
def say(self): # 定义say实例方法
self.catalog = 7
# name、age以及catalog都是实例变量
# __init__() 函数在创建类对象时会自动调用,而say()方法需要类对象手动调用
# Test类的类对象都会包含name和age实例变量,只有调用了say()方法的类对象,才包含catalog实例变量
TEST = Person() # 只有调用say(),才会拥有catalog实例变量
TEST.say()
print(TEST.catalog)
# 类方法中还可以定义局部变量,局部变量以“变量名=值”的方式进行定义
class Price :
def count(self,money): # 定义say实例方法
sale = 0.8*money
print("优惠后的价格为:",sale)
TEST= Price()
TEST.count(100)
# 优惠后的价格为: 80.0
# 定义局部变量是为了所在类方法功能的实现,局部变量只能用于所在函数中,函数执行完成后,局部变量也会被销毁
# 实例方法:定义在类中的函数:def 方法名 (self):
class Person:
#类构造方法,也属于实例方法
def __init__(self):
self.name = "李四"
self.age = "20"
# 下面定义了一个say实例方法
def say(self):
print("正在调用 say() 实例方法")
# 实例方法调用:
# 1.实例方法通常会用实例对象.方法名()调用
test1 = Person()#创建一个实例对象
test1.say()
# 2.实例方法也可以使用类名调用,但是此方法需要手动给self参数传值
# 格式:类名.方法名(实例对象)
test1 = Person()
Person.say(test1)
# 类方法:和实例方法相似,它最少也要包含一个参数,只不过类方法中通常将其命名为cls,Python 会自动将类本身绑定给cls参数
# 类方法需要使用@classmethod修饰符进行修饰
class Person:
#类构造方法,也属于实例方法
def __init__(self):
self.name = "王五"
self.age = "26"
#下面定义了一个类方法
@classmethod
def info(cls):
print("正在调用类方法",cls)
# 如果没有 @classmethod,则Python解释器会将info()方法认定为实例方法,而不是类方法
# 类方法推荐使用类名直接调用
#使用类名直接调用类方法
# property()函数
# 在不破坏类封装原则的前提下,依旧使用“类对象.属性”的方式操作类中的属性
# 属性名=property(fget=None, fset=None, fdel=None, doc=None)
# fget参数:指定获取该属性值的类方法
# fset参数:指定设置该属性值的方法
# fdel参数:指定删除该属性值的方法,最后的doc是文档字符串,说明此函数的作用
# property() 函数中参数的指定并不是完全随意的,可以仅指定第1个、或前2个、或前3个,也可以全部指定
class Person:
def __init__(self, n): # 构造函数
self.__name = n
def setname(self, n): # 设置 name 属性值的函数
self.__name = n
def getname(self): # 访问nema属性值的函数
return self.__name
def delname(self): # 删除name属性值的函数
self.__name = "xxx"
name = property(getname, setname, delname, '说明文档') # 为name 属性配置 property() 函数
# 说明文档,print(test.name.__doc__)
help(Person.name)
TEST = Person("you")
print(TEST.name) # 调用 getname() 方法
TEST.name = "胡汉三" # 调用 setname() 方法
print(TEST.name)
del TEST.name # 调用 delname() 方法
print(TEST.name)
# getname()方法中需要返回name属性,如果使用self.name的话,其本身又被调用getname(),会进入死循环
# name属性必须设置为私有属性,即__name
# name = property(getname, setname)
# name是一个可读写的属性,但不能删除,因为函数中并没有为name配置用于函数该属性的方法
# Person类中设计有delname()函数,这种情况下也不能用来删除name属性
# Python 继承
# 继承允许我们定义继承另一个类的所有方法和属性的类。
# 父类是继承的类,也称为基类。
# 子类是从另一个类继承的类,也称为派生类。
# object 类是 Python 中所有类的父类
# python中类的继承包括 单继承和多继承
# 语法格式:
# class 类名(父类1, 父类2, ...):
# 类定义部分
class ParentClass1: #定义父类
pass
class ParentClass2: #定义父类
pass
class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
pass
class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
pass
# 父类重写:子类继承父类后,个别类方法并不适用,对这类方法进行修改
class Bird:
#鸟有翅膀
def isWing(self):
print("鸟有翅膀")
#鸟会飞
def fly(self):
print("鸟会飞")
class Ostrich(Bird):
# 重写Bird类的fly()方法
def fly(self):
print("鸵鸟不会飞")
# 创建Ostrich对象
ostrich = Ostrich()
#调用 Ostrich 类中重写的 fly() 类方法
ostrich.fly()
# 调用父类中被重写的方法
# 调用父类中被重写的方法
class Bird:
#鸟有翅膀
def isWing(self):
print("鸟有翅膀")
#鸟会飞
def fly(self):
print("鸟会飞")
class Ostrich(Bird):
# 重写Bird类的fly()方法
def fly(self):
print("鸵鸟不会飞")
# 创建Ostrich对象
ostrich = Ostrich()
#调用 Bird 类中的 fly() 方法
Bird.fly(ostrich)
#使用 类名调用其类方法,Python 不会为该方法的第一个 self 参数自定绑定值,因此采用这种调用方法,需要手动为 self 参数赋值。
# 在子类中调用父类同名的方法
# 两种方式:
# 1. 父类名.方法名(self)
# 2. super().方法名()
# Python 3.x 中,super() 函数有一种更简单的语法格式
# super().__init__(self,...)
class People:
def __init__(self,name):
self.name = name
def say(self):
print("我是人,名字为:",self.name)
class Animal:
def __init__(self,food):
self.food = food
def display(self):
print("我是动物,我吃",self.food)
class Person(People, Animal):
#自定义构造方法
def __init__(self,name,food):
#调用 People 类的构造方法
super().__init__(name)
#super(Person,self).__init__(name) #执行效果和上一行相同
#People.__init__(self,name)#使用未绑定方法调用 People 类构造方法
#调用其它父类的构造方法,需手动给 self 传值
Animal.__init__(self,food)
per = Person("zhangsan","熟食")
per.say()
per.display()