Python3学习笔记_类和对象_20200514/0516
21、类和对象
1》概念
什么是类?
俗话说:人以群分,物以类聚,种类/分类
英文:class
群体
什么样的东西可以形成一个类?
人类、禽类、兽类
因为他们有相似点,有共同之处
#示例1:
白敬亭:男
易烊千玺:男
-----------男人类
class Man:
pass
什么是对象?object
又被称为实例:instance
object:东西
是一个群体当中的成员/个体
Man 类里面的对象:白敬亭、易烊千玺
2》类和对象在Python中的表示
class 类名:
类的组成部分
①
class Man:
pass
②
class Man(): #()加不加都可以
pass
③
class Man(object):
pass
类的调用:
print(类名) 或者
变量=类名
#示例1:
new_man=Man
print(new_man) #结果:<class '__main__.Man'>
#看到有尖括号的,一般来说就是一个类/对象
print(Man) #结果:<class '__main__.Man'>
对象的表示方法:
类名()
print(Man()) #结果:<__main__.Man object at 0x1016c84e0>
#示例2:
a=Man()
b=Man()
print(a)
print(b)
print(a is b) #身份运算, a和b不是同一个成员,是两个对象,内存地址是不一样的
#经典面试题:
print(Man() is Man())
#如何去进一步确定是不是同一个对象,可以去打印对象id
print(id(a))
print(id(b))
类的命名:
大驼峰式命名
两个单词的首字母大写
class PerfectManHelp
函数的命名:
下划线命名
perfect_man_help
变量命名:
下划线命名
#示例3: 一个对象可能属于多个类【既可以是男人类,又可以是菜鸟类】
class Cat:
pass
jiafei=Cat()
tom=Cat()
blue=Cat()
black=Cat()
dragon=Cat()
print(jiafei)
print(tom)
print(blue)
属性:
什么是属性?表示的是类/对象的特征
特征是别人不具备的
类属性(类变量):
这个类的特征,这个群体的特征,别的类可能不具备
实例属性(实例变量):
个体的特征,类当中的其他成员可能不具备
定义类属性:
class Man:
gender='男'
power='强'
类属性的获取:类名.属性
print(Man.gender) #Man类的gender属性
print(Man.power) #Man类的power属性
类添加属性:(后天学习,手工添加)
Man.hello='hello world'
print(Man.hello)
总结:类属性可以先天定义,也可以后天学习,也就是添加
实例属性的获取(后天学习):
yuz=Man()
yuz.handsome='very'
print(yuz.handsome)
print(lemon.handsome) #会报错,因为不具备,为了不报错,也要添加这个属性才可以
lemon.handsome='much'
print(lemon.handsome)
#如果想所有的实例都具有这个属性,则需要在类里面定义这个属性
#思考题:如果类中定义了这个属性值,然后实例中又重新添加了这个属性值,则最后得到的属性值应该是实例添加后的
class Man:
gender='ddd'
a=Man()
a.gender='hhh'
print(a.gender) #得到的属性值是:hhh
#示例5:区别1
class Man:
gender='男'
power='强'
#类属性:所有的成员都是一样的
yuz=Man()
kaishi=Man()
print(yuz.gender)
print(kaishi.gender)
#实例属性,不是每个成员都一样
yuz.eye='蓝色'
print(kaishi.eye) #报错:AttributeError,没有这个属性
#示例6:区别2
#类属性,可以被实例、对象访问
#示例属性,不可以被类获取
print(Man.eye) #报错:AttributeError,类没有这个属性
方法:表示类、对象的行为
本质上是一个函数,只不过是一个特殊的函数
属性:名字
方法:动词
方法 VS 函数:
1、self
2、放在类里面,缩进的
3、调用过程不一样,方法需要加前缀,类名或者对象名
函数前面要么不加,要么加模块名
#示例7:
class Man:
gender='男'
power='强'
handsome='very very'
def drink(self):
pass
def play_game(self):
pass
#方法调用的第一种方式:对象.方法()
Man().drink()
#方法调用的第二种方式:
yuz=Man()
yuz.drink()
Man.drink() # 报错:TypeError: drink() missing 1 required positional argument: 'self'
# 因为drink行为属于某一个人的,不是属于所有类成员的,不能被类调用
#实例方法、对象方法:
1、第一个参数名称,规定是self
2、实例方法在调用的时候,前缀是对象,不能是类
#类方法:
1、在方法的上面,添加@classmethod
2、把实例方法当中的self改为:cls
#示例8:
class Man:
gender='男'
power='强'
handsome='very very'
@classmethod #装饰器,加这个表示是类方法,不加就是实例方法
def eat(cls):
print('正在吃饭')
def drink(self):
pass
def play_game(self):
pass
#打印函数的调用打印出来的是函数的返回值
print(Man.eat())
print(Man().eat())
def run():
return
print(run()) #打印结果:None,打印函数的调用打印出来的是函数的返回值
#静态方法:
静态方法表示:方法的上面加上一个@staticmethod
不需要用self,cls作为固定参数
静态方法是刚刚好放在一个类当中的普通函数而已
除了放在类当中,和普通函数没有什么区别
没有实际的作用,和类或者对象没有关系,(但不代表没有联系)
为什么要用静态方法,为什么要把普通的函数放到类当中去?
为了方便管理
#示例9:
class Man:
gender='男'
power='强'
handsome='very very'
@staticmethod
def tianqiyubao():
print('天气预报:今天是晴天。')
@classmethod
def eat(cls):
print('正在吃饭')
def drink(self):
pass
def play_game(self):
pass
#静态方法的调用:
Man.tianqiyubao()
#示例9相当于示例10:静态方法和普通函数没什么区别
#示例10:
def tianqiyubao():
print('天气预报:今天是晴天。')
class Man:
gender='男'
power='强'
handsome='very very'
@classmethod
def eat(cls):
print('正在吃饭')
def drink(self):
pass
def play_game(self):
pass
#调用静态方法:
静态方法:(普通函数)只需要在调用静态方法时,前面加上类名或对象名
类外面的普通函数:普通函数的调用,不需要加类名,只需要加模块名
Man.tianqiyubao()
Man().tianqiyubao()
tianqiyubao() #这样是不可以的,报错:NameError: name 'tianqiyubao' is not defined
#实际使用当中:
实例方法:占98%,实例方法占大多数情况
不知道用什么方法,就用实例方法
类方法:后面会有特殊情况
静态方法:可以用普通函数代替,不是必须的,为了管理方便
对象的初始化和self:
什么是初始化?(实例化)
要通过定义的类,得到一个具体的对象,生出来,造出来
对象个体,初始化过程需要每个对象不一样
我们自己给东西进行出厂设置
在特定的方法当中去控制__init__
#示例11:
class Man:
gender='男'
power='强'
handsome='very very'
def __init__(self):
"""对象的初始化过程,让对象之间长得不太一样"""
#定义,在类里面,定义实例属性,使用self.属性=...
self.face='方脸'
pass
#实例属性的定义:
1、类外面,对象名.属性 ----后天学习的
2、类里面,self.属性 ----先天的
__init__定义的形式参数 和 对象的实例化a=Man()的实际参数,是一一对应的
__init__必须return None
__init__传入的参数必须要设置成实例属性,才能被对象访问到
#实例12:
class Man:
gender='男'
power='强'
handsome='very very'
def __init__(self,face_shape,name):
"""对象的初始化过程,让对象之间长得不太一样"""
#定义,在类里面,定义实例属性,使用self.属性=...
self.face=face_shape
self.name=name
yuz=Man() #报错:TypeError: __init__() missing 1 required positional argument: 'face_shape'
#因为声明对象的时候,需要传参数,传__init__方法所需要的参数
yuz.gender
#应该是:
yuz=Man('圆脸','lemon') #__init__定义的形式参数 和 对象的实例化a=Man()的实际参数,是一一对应的
print(yuz.gender)
print(yuz.face)
print(yuz.name)
__init__方法中,可以设置默认参数
#示例13:
class Man:
gender='男'
power='强'
handsome='very very'
def __init__(self,name,face_shape='圆脸'):
"""对象的初始化过程,让对象之间长得不太一样"""
#定义,在类里面,定义实例属性,使用self.属性=...
self.face=face_shape
self.name=name
yuz=Man('lemon')
print(yuz.name)
yuz=Man('lemon','方脸')
print(yuz.name)
print(yuz.face)
#整容的权利,可以后天改变属性
yuz.face='帅脸'
print(yuz.face)
#示例14:
class Man:
gender='男'
power='强'
handsome='very very'
def __init__(self,name,face_shape='圆脸'):
"""对象的初始化过程,让对象之间长得不太一样"""
#定义,在类里面,定义实例属性,使用self.属性=...
self.face=face_shape
self.name=name
return #这样是OK的
#示例15:
class Man:
gender='男'
power='强'
handsome='very very'
def __init__(self,name,face_shape='圆脸'):
"""对象的初始化过程,让对象之间长得不太一样"""
#定义,在类里面,定义实例属性,使用self.属性=...
self.face=face_shape
self.name=name
return 1 #这样会报错,必须return None
#示例16:
class Man:
gender='男'
power='强'
handsome='very very'
def __init__(self,name,face_shape='圆脸'):
"""对象的初始化过程,让对象之间长得不太一样"""
#定义,在类里面,定义实例属性,使用self.属性=...
self.face=face_shape
# self.name=name
yuz=Man('lemon','方脸')
print(yuz.name) #报错,因为__init__里面没有将name设置成实例属性
self:在***类***里面,表示一个***对象***它自己,占坑符
没有self,就用不了这个类或者是对象中的其他属性或方法
在读取类的时候,会先读取类里面所有顶格写的代码
cls:在***类***里面,表示一个***类***它自己,占坑符
#示例17:
class Man:
gender='男'
power='强'
handsome='very very'
def __init__(self,name,face_shape='圆脸'):
"""对象的初始化过程,让对象之间长得不太一样"""
#定义,在类里面,定义实例属性,使用self.属性=...
self.face=face_shape
self.name=name
@staticmethod
def tianqiyubao():
print('天气预报:今天是晴天。')
@classmethod
def eat(cls):
print('正在吃饭')
self.drink() #不可以这样写,类方法是不可以调用实例方法的
print(cls.gender) #这样写是OK的,可以获取类属性
def drink(self):
print('{}正在喝酒'.format(self.name)) #这样写是OK的,可以获取这个对象的其他属性
self.play_game() #这样写是OK的,可以获取这个对象的其他方法
self.eat() #这样写是OK的,对象可以获取这个类方法
def play_game(self):
print('玩游戏')
#问题1:实例方法中可以定义实例属性吗?
#实例18:
class Man:
gender='男'
power='强'
handsome='very very'
def __init__(self,name,face_shape='圆脸'):
"""对象的初始化过程,让对象之间长得不太一样"""
#定义,在类里面,定义实例属性,使用self.属性=...
self.face=face_shape
self.name=name
@staticmethod
def tianqiyubao():
print('天气预报:今天是晴天。')
@classmethod
def eat(cls):
print('正在吃饭')
def drink(self):
print('{}正在喝酒'.format(self.name))
self.single=False #不可以这样写,这样写会报错
lemon=Man('lemon')
print(lemon.single) #初始化以后,single属性是后天定义的,先天的属性是放在__init__里面的,
#只有调用了drink()方法之后,single属性才存在
lemon.drink()
print(lemon.single) #只有调用了drink()方法之后,single属性才存在,才能获取
总结:
1、什么是类和对象?
类:具备相同特征或者行为的一个群体
对象:个体
类:模型(造对象)
对象:模型生出来(造出来)具体的东西
2、类属性和实例属性定义:
类属性定义:类名下面或者类外面,可以在其他的方法当中定义,但是不建议这样写
class 类名:
类属性1=属性值
def __init__(self,name):
self.name=name
类名.类属性2=属性值
实例属性定义:类里面和类外面,__init__方法定义或者类名().实例属性
先天具备的属性,实例属性通常在类名下面的__init__直接定义好
后天培养的属性,不管是类属性还是实例属性,都可以在其他的方法当中定义(不建议这样定义),或者是类外面定义
3、实例属性和类属性的区别:
1、实例可以获取实例属性和类属性
2、类只能获取类属性(类不能访问实例属性)
3、如果某一个属性名同时是类属性和实例属性,会优先使用实例属性,如果实例没有这个属性,则会使用类属性
示例:
class Man:
name='nan'
def __init__(self,name):
self.name=name
print(Man.name) #打印:nan
print(Man('lemon').name) #打印:lemon
注:如果在一个具体的场景当中,不知道这个属性用类属性还是实例属性???就用实例属性
4、方法:
实例方法:实例具备的,类不一定具备,类不能调用实例方法,实例方法可以通过self获取
类方法:类具备的,实例可以获取,类方法可以通过cls获取类
静态方法:放在类里面的函数
调用:类.静态方法 或者 对象.静态方法
5、init:生孩子的过程,出厂设置
是对象的初始化过程,通常在里面定义实例属性
实例属性的值通过参数传递进来
参数必须要赋值给实例属性,self.属性=参数,才能通过实例调用
注意:注意写法,不要写成:__int__
6、self和cls
self:
类定义的里面,表示的是对象
cls:
类定义的里面,表示的是类