- 理解面向对象
- 类和对象
- 添加和获取对象属性
1、基本概念
python是一门彻底的面向对象的编程语言OOP
类和对象的关系:用类去创建对象(用类去实例化对象),现有类才有对象
类是对一系列具有相同特征和行为的事物的统称,是一个抽象的概念,是不真实存在的事物。特征即变量、行为即函数
关注点:解决问题所需要的对象,将许多属性包装在一个对象中,面向对象是对面向过程的封装
面向对象最重要的是:找到对象,确定对象的属性和行为,按照对象功能进行划分成不同的类
类的作用:根据抽象的类生产具体的对象。比如差生包含多种属性(成绩差、体育差、思想差),可以构建出不同的差生对象:差生张三、李四、王五
类名首字母必须大写
class 类名():继承类、新式类 class 类名: 单纯的类、经典类
代码
对象名=类名() 对象名.print 输出对象
2、创建类
class Money:
pass
print(Money)
one = Money()
print(one)
one.__class__
Money.__name__ # 'Money'
id(Money.__name__) # 2331860393008 类名所在的位置
xxx=Money
xxx # __main__.Money
print(xxx.__name__) # Money
Money = 666
Money # 666
# 变量名money引用类名money
id(Money) # 2331860481232
one = Money()
print(one)
xxx=Money
print(xxx)
此时Money被当作两个东西来使用,一个是当前类的类名,一个是变量名。变量名引用类名,变量名和类名使用同一个地址。
根据Money类来创建一个对象one
3、对象属性
3.1 属性的特点
属性是指某个对象的特性,只能通过对象来进行访问,所以必须要先找到对象,对象是通过变量名来引用的,既然涉及到变量名,那么就涉及访问权限。有属主就是一个属性,没有属主则是一个变量。属性分为对象属性(属主是对象)和类属性(属主是类),比如Money是one的对象属性,__name__是Money的类属性。
# 类中也是有属性的
Person.home=1
print(Person.__dict__) # 'home': 1在dict中
3.2 属性的增删改查
不同的对象之间不能访问对方的属性
# 增删改查
#1、定义一个类
class Person:
pass
#2、根据类创建一个对象
p = Person()
#3、增加某个属性
p.age=18
p.weight=180
p.pet =['a','b']
print(id(p.age)) #1441911302992
print(p.__dict__)
# {'age': 18, 'weight': 180, 'pet': ['a', 'b']}
#4、改
p.age=20
print(id(p.age)) # 1441911303056 地址改变,新建了一个空间
print(p.__dict__)
# {'age': 20, 'weight': 180, 'pet': ['a', 'b']}
print(id(p.age))
# 5、删
del p.age
# 6、查
print(p.age) # 已经没有age了
print(p.__dict__) #{'weight': 180, 'pet': ['a', 'b']}
类属性的增删改查
python优先到对象自身去查找属性,找到则结束;如果没有找到则根据__class__找到对象对应的类中的属性。
# 类属性的增
# 方法一
class Person:
pass
Person.age=1
print(Person.__dict__) # 'home': 1在dict中
# 方法二
class Person: # 重新定义的Person
age = 123
num = 456
pass
print(Person.__dict__) # 'age': 123, 'num': 456
print(Person.age) #123
# 查
one = Person()
one.__class__ # __main__.Person
one.age # 123 # 当对象没有该属性时,使用类的属性
one.age = 12
one.__dict__ # {'age': 12}
one.age # 12 # 当对象有该属性时,使用对象的属性
Person.age #123
one.num # 456
# 改
# 只能对通过类属性修改,不能通过对象属性修改
# 如果对象本来就存在该属性,则只修改了对象属性而没有修改类属性
# 如果对象属性中没有该属性,则修改语句实际上是新增一个对象属性
Person.age=90
print(Person.age) # 90
del one.age
print(one.__dict__) # {}
one.age=8
print(one.__dict__) # {'age': 8}
# 删
# del语句只能删除直系属性
# 不能通过对象去删除类属性
Person.__dict__ #'age': 90,'num': 456
del one.num # Person中有num,但是该命令报错
del Person.num
Person.__dict__ # 'age': 90
Person.__dict__类属性字典是一个只读的,不能修改的,one.__dict__对象属性字典是可读可改的
Person.__dict__={"sex":"1"}
Person.__dict["age"]=100
one.__dict__={"sex":"1"}
one.__dict__["age"]=100
one.__dict__ # {'sex': '1', 'age': 100}
类属性被各个对象共享
class Person():
age=12
sex=1
pass
one=Person()
two=Person()
Person.__dict__ # 'age': 12, 'sex': 1,
one.__dict__ # {}
two.__dict__ # {}
Person.age #12
one.age #12
two.age #12
Person.age=30
one.age #30
two.age #30
类属性增、删、改都只能通过类操作,不能通过对象操作;只有查,如果没有该对象属性,则可以通过对象属性查询。
class Person():
age=10
pass
p=Person()
p.age #10
p.age +=5
p.age # 15 通过对象访问age的值
Person.age # 10 # 并不能改变类属性的值
通过__slots__对对象可以添加的属性进行限制
class Person():
__slots__=["age","sex"]
pass
p = Person()
p.age=12
p.sex=1
p.num=1234
4、方法
实例方法的第一个参数要求接收一个实例;类方法的第一个参数要求接收一个类;静态方法参数没有要求。打完()之后,会自动填充括号内的参数类型
class Person:
def eat(self):
print("这是一个实例方法",self)
@classmethod
def eat2(cls):
print("这是一个类方法",cls)
@staticmethod
def eat3():
print("这是一个静态方法")
p=Person()
p
p.eat() #这是一个静态方法 将p传给eat()
p.eat2() #这是一个类方法 <class '__main__.Person'>
Person.eat2() # 这是一个类方法 <class '__main__.Person'>
Person.eat() # Person是对象,无法调用实例方法
Person.__dict__
4.1 实例方法
class Person:
def run(self,food): # self表示实例方法第一个参数是接收实例本身
print("在吃饭,", food)
print("在吃饭,",self,food)
pass
p = Person() # 创建实例p
print(p)
p.run("土豆") # 实例p在调用run时,会自动将自己传给self
self和p的地址相同,说明实例p将自身传给run
实例方法的第一个参数只能传实例,不能传类
class Person:
def eat():
print("xxx")
def eat2(xxx):
print("000")
p=Person()
p.eat2()
p.eat()
默认会把p传给eat的第一个参数,然而此时eat函数中没有参数,因此报错,eat()需要0个参数,却给了1个参数(p);eat2(xxx)第一个参数可以不用self命名,用任何变量名都可以,但是规范用法是self
4.2 类方法
通过函数装饰器,来定义一个类方法,类方法的第一个参数是传递类;如果是一个实例来调用类方法,则是将实例中的类传递到第一个参数。装饰器的作用是在保证原函数不改变的前提下,直接给这个函数增加一些功能。
class Person:
@classmethod
def leifangfa(cls,a):
print("这是一个类方法",a)
Person.leifangfa(123)
p=Person()
p.leifangfa(666)
fuc=Person.leifangfa
fuc(89)
class A(Person):
pass
A.leifangfa(789)
4.3 静态方法
l=[3,5,1,8,2]
l.sort(reverse=True)
# sort相当于一个静态方法,对于第一个参数没有类型限制
class Person:
@staticmethod
def jingtai():
print("这是一个静态方法")
Person.jingtai()
p=Person()
p.jingtai()
fuc=Person.jingtai
fuc()
4.4 生成说明文档
python -m pydoc test #在终端显示test模块的说明文档
python -m pydoc -p 1234 # 启动本地服务,浏览器浏览文档
python -m pydoc -b # 自动分配一个iP地址启动浏览器
python -m pydoc -w test # 在该目录下生成模块test的html文档
python -m pydoc -h # 查看pydoc的帮助文档
在终端使用pydoc直接生成说明文档网页 -m:模式 -p:ip地址 -h:help
5. 补充知识
5.1 经典类和新式类
经典类:没有继承object
新式类:继承了object