类与对象
面向对象编程是以类(class) 与 对象(object)两种数据结构组织代码的
‘基本概念’ :类实际上就是一种现实生活中个体特征相似的抽象的集体概念,是一个人们抽象出来的集体概念,不存在于现实。而对象是类的一员,是实际生活中,我们可以触碰到,可以观察到的客观存在的人事物的个体。拥有相对(或者类似)特征和行为的对象就可以抽象出一个类。因此 类是对象的抽象,而对象是类的具体
类的声明
#python中类的语法 class 类名(object): """类的说明文档""" 类属性 = 数据 @classmethod def 类方法名(cls [,参数列表]): 函数代码,一般编写用于操作类属性的代码
类的结构
由三部分组成
类名称:用于区分不同分类的变量名,采用大驼峰命名法
类属性:记录同一个类的所有对象的公共数据变量
类方法:操作同一个类的所有对象的公共数据的函数
类属性实际上就是一组对象的共同变量,类方法实际上就是一组对象的公共函数
如,人类设计: - 类名称:人(Person、Humen) - 类属性:手的数量(hand_length),腿的数量(leg_length)、眼睛的数量(eye_length),最大年龄(max_age)等。 - 类方法:跑(run)、说话(speak)、吃(eat) # Person就是类名称 class Person(object): # 一个类可以有0 个或多个类属性 eye_length = 2 leg_length = 2 hand_length = 2 max_age = 150 #类方法,必须在函数上方一行加上@classmethod 用于区分普通函数与后面学到的对象方法 @classmethod def run(cls): #cls是类方法的第一个固定参数,变量名必须叫cls,代表当前类 print("跑") #函数内部就是普通函数代码,当然也可以通过cls 调用当前类的其他类属性或者类方法 #一个类可以有0个或多个方法 @classmethod def eat(cls,food): print(f"吃{food}") #类的操作 在类的外界调用类属性或类方法,必须使用类名,作为前缀,否则会变成访问其他的变量或函数 #类的属性调用: print(Person.eye_length) #修改类属性:Person.eye.length = 4 #类方法的调用: Person.run()
对象
‘对象的实例化’:对象声明就是对象实例化的过程,必须通过类来创建,所以创建对象之前,必须先声明类,类可以是开发人员自己定义的,也可以是python内置的
"""先声明类,后调用类创建对象,就可以完成实力化的过程""" class Person(object): """人类""" pass print(Person, id(Person)) """一个类可以实例化1个或多个对象""" xiaoming = Person() print(xiaoming, id(xiaoming)) xiaohong = Person() print(xiaohong, id(xiaohong)) xiaobai = Person() print(xiaobai, id(xiaobai)) # 查看类型 print(type(xiaoming)) print(type(xiaohong)) print(type(xiaobai)) # 判断一个对象是否是否某个类的实例 print( isinstance(xiaoming, Person)) # True print( isinstance(xiaohong, Person)) # True print( isinstance(xiaobai, Person)) # True class Dog(object): pass print(isinstance(xiaoming, Dog)) # False
对象的结构
对象有两个部分组成:
-属性:记录当前对象独有特征(描述对象的相关数据)的变量。也叫(特征,对象属性,实例属性)
-方法:操作当前对象独有特征的函数(也叫行为,对象方法,实例方法)
因为对象是类创建出来的,所以对象的属性和方法基本都是写在类里面的,在类创建对象以后,提供给对象
clas Person(object): #每一个对象,如果有属性,则属性一般写在__init__构造方法中 #对象的每个实例方法必须有至少一个参数,而且第一个参数固定必须叫self,代表当前对象 def __init__(self, name,age,money) #构造方法,是一个固定函数名的魔术实例方法,在初始化对象时自动运行,并把类后面的参数提取作为自己的参数 #在构造方法中的代码,一般就是对象的实例属性声明的代码,当然,也可以编写一些对象初始化时就要执行的代码 self.name = name self.age = age self.money = money #实例方法有别于类方法,不需要加上@classmethod def save_money(self,money) """存钱""" #在对象中如果要修改或访问对象的其他方法或属性,需要使用self. 开头作为前缀,否则会变成访问全局变量 self.money += money def get_money(self, money): """取钱""" self.money -= money def introduction(self): """自我介绍""" print(f"我叫{self.name},今年{self.age}岁。")
对象操作
在类中声明了对象相关的实例属性和实例方法以后,我们就可以在类的外面实例化对象,并通过对像调用和访问对象的实例属性和实例方法
class Person(object): def __init__(self, name, age, money): self.name = name self.age = age self.money = money def introduction(self): return f"我叫{self.name},今年{self.age}岁" def save_money(self, money): self.money += money # 实例化对象 xiaoming = Person("小明", 17, 1000) #类后面的参数会作为__init__的参数,自动传递进去 print(xiaoming) #小明是一个变量,但是这个变量被对象赋值了,所以变量名就成了对象名 #调用对象的属性 print(f"这个人叫{xiaoming.name},今年{xiaoming.age}岁") #修改对象的属性 xiaoming.name = "李晓明" print(f"这个人叫{xiaoming.name},今年{xiaoming.age}岁") #调用对象的方法 print(xiaoming.introduction) ''' 对象的实例属性和实例方法的调用:1.在类的内部,通过self. 进行调用 2.在类的外部通过对象名. 进行调用 ''' # 一个类可以实例化多个对象,不同的对象的属性值可以是不一样的,不同对象的信息保存在不同的内存地址中。 xiaohong = Person("小红", 15, 2200) print(f"这个人叫{xiaohong.name},今年{xiaohong.age}岁!") # 修改对象的属性 xiaohong.name = "红太狼" xiaohong.age += 1 print(f"这个人叫{xiaohong.name},今年{xiaohong.age}岁!") """ 同一个类实例化出来的不同对象, 所拥有的实例属性和实例方法,都是相互独立,互不干扰的、 """ # 调用对象的方法 print(xiaohong.introduction())
因为类属性和类方法时所有对象共同拥有的特征和行为,所以实例化以后的对象也可以调用类属性和类方法
dlass Dog(object): # 类属性列表 eye_length = 2 leg_length = 4 max_age = 30 tail_length = 1 def __init__(self, name, age): """实例属性列表""" self.name = name self.age = age @classmethod def run(cls): # 在类中如果要修改或访问当前类的其他类方法或类属性,需要使用cls.开头作为前缀,否则会变成访问全局变量。 print(f"{cls.leg_length}条腿交叉跑") @classmethod def wag_tail(cls): return "摇尾巴" def get_guide(self, where): print(f"导盲去{where}") xiaoqiang = Dog("小强", 7) # 对象访问类属性 print(f"我家的狗[{xiaoqiang.name}]今年{xiaoqiang.age}岁了,但是它能活{xiaoqiang.max_age}年。") wangcai = Dog("旺财", 3) print(f"我家的狗[{wangcai.name}]今年{wangcai.age}岁了,但是它能活{wangcai.max_age}年。")
"""不同对象所有拥有的类属性和类方法,是一模一样的。而且内存地址也是一样的。"""
# 给类新增属性 Dog.skill_list = ["打架", "拆迁"] # 证明不同对象所有拥有的类属性和类方法,是一摸一样的,而且内存地址也是一样的 print(id(Dog.skill_list)) print(id(xiaoqiang.skill_list)) 对象虽然可以访问类属性和调用类方法,但是对象无法修改类属性和类方法。同时,类是无法访问对象的实例属性与实例方法
声明类属性/类方法与声明实例属性/实例方法
当有些变量是所有对象都共同拥有的,那么就应该把这些变量作为类属性进行声明,达到节约内存的作用。有些变量是每一个个体数值都不一样的,那么这些变量就应该作为实例属性进行声明。同理,操纵类属性的方法,就应该采用类方法进行声明,而操作实例属性的,就应该采用实例方法来声明。
静态方法
如果有些方法,本身在函数内部既没有调用到类属性,也没有调用到实例属性。那么就应该作为静态方法来进行声明。当然,静态方法的使用,仅仅是一种规范,而实际工作中,很多开发人员也会把不操作类或对象数据的方法,使用实例方法或类方法来声明,这也是可以的。
静态方法声明了以后,不仅对象可以调用,类也可以调用
""" 静态方法的声明,与实例方法、类方法不一样,实例方法和类方法,在声明时都需要保留一个参数作为当前类或当前对象的变量,而静态方法不会有。 同时,实例方法、类方法在调用时和静态方法是一样,实例方法的self,类方法的cls不需要我们手动传递,python语法会自动传递。 """