类和对象
1 类和对象的概念
1.1 对象和类的概念以及关系
对象 是特征与技能的结合体,是真实存在的
类 是一系列对象相似的特征与技能的结合体,是对对象的藐视,是一个概念,不是真实存在的
对象是类的实例,类是对象的抽象。 一个对象只能对应一个类,而一个类可以产生很多对象
1.2 先有类还是先有对象
先有的一个个具体存在的对象(比如一个具体存在的人),还是先有的人类这个概念,这个问题需要分两种情况去看
在现实世界中:先有对象,再有类
世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念
也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在
在程序中:务必保证先定义类,后产生对象
这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类
不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象
1.3 python中的一切皆对象
很早我们就说过,在python中,一切皆对象。 也就是一个数字、一个字符串、一个函数等等都是对象。
python中的数据类型其实就是类,比如12
、45
、4
这是三个对象,这三个对象对应的类都是int
,[10,23,45]
、['dandan', 'lili']
这是两个对象,这两个对象对应的类是list
。
而当现有的数据类型无法表示一类数据的时候,就需要我们自己去定义类了
结合python中的数据类型,我想我们可以更好地理解类和对象的关系
2 类和对象的定义
现实中:我们把每个学生当做一个对象,需要定义一个学生类
程序中:先定义类,根据类实例化学生对象
#在现实世界中:先有对象,再有类
对象1:西门庆
特征:
学校=阳光幼儿园
姓名=曹操
性别=男
年龄=68
技能:
学习
吃饭
睡觉
对象2:潘金莲
特征:
学校=阳光幼儿园
姓名=潘金莲
性别=女
年龄=28
技能:
学习
吃饭
睡觉
对象3:武大郎
特征:
学校=阳光幼儿园
姓名=武大郎
性别=男
年龄=17
技能:
学习
吃饭
睡觉
现实中的对象有特征和技能组成,程序中的对象对应就是 属性和方法
响应的,定义类的时候也要添加属性
# 类名 命名规范同变量名
# 通常首字母大小
class Student:
# 初始化方法
# 在对象实例化的时候, 会自动调用
# 通常用来给实例添加属性
# 该方法内不能有返回值
def __init__(self, value1, value1):
self.prop1 = value1
self.prop2 = value2
# 类中方法
def 方法名(self, 形参):
# self 表示的是 调用该方法的对象
# 通过self 可以调用对象的其他属性和方法
# 方法本质上也是个 属性 方法名就是属性名
# self也可以叫其他名字,通常叫self
# 方法就是个函数,参数形式有 普通参数、可变数量参数、命名关键字参数、关键字参数; 也可以有return, return 同样会结束方法的执行。也可以给方法加 装饰器
# 实例化对象
# 对象会具有类中定义的属性和方法
对象 = 类名(参数1, 参数2)
# 调用方法 self不需要指定,指定self后面的其他参数
对象.方法(参数)
# 定义学生类
class Student:
# 初始化函数
# 在实例化的时候 自动调用
# 该方法内不能有返回值
def __init__(self):
self.school = '剑桥大学'
self.nam = '牛顿'
self.sex = '男'
self.age = 18
def eat(self):
print('我能吃')
def drink(self, drinks):
print('我喝%s' %drinks)
def sleep(self):
print('我能睡')
# 实例化 成对象
s1 = Student()
# 输出对象
print(s1)
# 返回对象的类型 类型就是类
print(type(s1))
# 调用对象的方法
s1.eat()
s1.drink('红牛')
# 输出对象属性
print(s1.name, s1.age, s1.sex, s1.school)
# 修改对象的属性
s1.name = '马顿'
print('我的名字改成了:'+s1.name)
# 给对象添加属性
s1.grade = '一年级'
print(s1.grade)
print()
s2 = Student()
print(s2)
print(type(s2))
s2.eat()
s2.drink('自来水')
print(s2.name, s2.age, s2.sex, s2.school)
# print(s2.grade)
# 定义学生类
# 类名命名规范同变量的命名规范 通常首字母大写
class Student:
# 初始化函数
# 在实例化的时候 自动调用
def __init__(self, school, name, sex, age):
self.school = school
self.name = name
self.sex = sex
self.age = age
def eat(self):
print('我能吃')
def drink(self, drinks):
print('我喝%s' %drinks)
def sleep(self):
print('我能睡')
def say(self):
print('打扎好,我死%s,我今年%s岁,我是%s人,我在%s读书' %(self.name, self.age, self.sex, self.school))
self.sleep()
# 实例化对象
s1 = Student('西点军校', '曹操', '男', 19)
print(s1.school, s1.name, s1.sex, s1.age)
s1.say()
print()
# 实例化对象
s2 = Student('黄埔军校', '曹丕', '男', 29)
print(s2.school, s2.name, s2.sex, s2.age)
s2.say()
3 类属性和实例属性
class Person:
# 类属性
name = '丹丹'
hometown = '地球'
def __init(self, name, age):
# 对象的属性,实例属性
self.name = name
self.age = age
# 给对象添加方法 没有意义,通常对象的方法 使用 类的方法 就可以
def demo():
pass
self.demo = demo
# 这些方法其实都是 类属性 方法本质上也是属性
def eat(self):
pass
def sleep(self):
pass
# 如果不写第一个形参,通过对象调用该方法 会报错
def dirnk():
pass
p = Person() # 实例化
p.name # 优先使用对象的属性
p.hometown # 对象如果没有homedown属性,会从类属性中查找
p.hometown = 值 # 不会修改类的属性, 而是给对象添加了新的属性 仅仅是p这一个实例
p.eat() #自动穿第一个参数,穿的是p本身
# 通过类名 直接使用类的属性和方法
Person.name
Person.hometown
Person.eat(参数必须写)
# 为了统计学生人数,可以给Student类增加一个类属性,每创建一个实例,该属性自动增加
lass Student():
count = 0
def __init__(self):
Person.count += 1 # 直接修改类的属性
总结:
实例属性属于各个实例所有,互不干扰;大部分属性会定义为实例属性
类属性属于类所有,所有实例共享一个属性;方法一般会定义为类属性,需要所有实例共享的定义为类属性
访问某个属性时会先从实例属性中找,找不到去类属性中找
不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误。
4 对象相关函数
type(object) # 返回一个对象的类
isinstance(object, class) # 判断一个对象是否是某个类的实例
dir(object) # 返回列表,里面是对象所有可访问的属性
hasattr(object, 'attrName') #判断一个对象中是否存在某个属性
setattr(object, 'attrName', value) # 给对象设置一个属性
getattr(object, 'attrName' [,defaultValue]) # 获取某个属性的值,可以指定默认值
5. 对象和类的内置特殊属性
# 对象的内置特殊属性
object.__dict__ # 字典,所有的实例属性(仅仅只有实例属性)
object.__dir__() # 列表,所有的属性,同dir()函数的返回结果相同
object.__class__ # 该对象的类, 与type()函数的返回结果一样
object.__module__ # 对象所在的模块,类似于全局变量 __name__
object.__doc__ # 类中的注释
# 类的内置特殊属性
类名.__name__ # 类的名字(字符串)
类名.__doc__ # 类的文档字符串
类名.__base__ # 类的第一个父类(在讲继承时会讲)
类名.__bases__ # 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__ # 类的字典属性
类名.__module__ # 类定义所在的模块
类名.__class__ # 实例对应的类
6 面向对象三大特性
封装
封装就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
继承
继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
多态
多态就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。