关于面向对象大体分了六大部分来学习,以下是这六部分的学习知识链接。
- 初识面向对象——类的定义和调用,属性和方法以及名称空间
- 再识面向对象——面向对象的组合用法
- 再识面向对象——面向对象的三大特性:继承
- 再识面向对象——面向对象的三大特性:封装
- 再识面向对象——面向对象的三大特性:多态
- 面向对象进阶——待续
——————————————–
初识面向对象
一、类的定义和调用
1, 类的定义
class Cat: # 类的定义
name = 'kitty' # 静态属性,数据属性,属性
def action(self): # 动态属性,函数属性,方法
pass
print(Cat.__dict__) # 查看类的属性和方法
>>>
{'__module__': '__main__', 'name': 'kitty', 'action': <function Cat.action at 0x000000000231EF28>, '__dict__': <attribute '__dict__' of 'Cat' objects>, '__weakref__': <attribute '__weakref__' of 'Cat' objects>, '__doc__': None}
类的定义:
class关键字 + 类名:
类名:是普通变量,遵循变量的定义规范,但是约定俗成首字母要大写。
静态属性,又被称作数据属性,可以理解为是定义在类内部的赋值语句,常被称作属性。
动态属性,又被称作函数属性,可以理解为是定义在类内部的函数,常被称作方法。
类名.__dict__方法 以字典的形式返回类内的所有属性和方法。
2,类属性的增删改查
1) 使用__dict__
方法
print(Cat.__dict__['name']) # 查看类内的属性
print(Cat.__dict__['action']) # 查看类内的方法
>>>
kitty
<function Cat.action at 0x0000000001F5EF28>
修改呢?
Cat.__dict__['name'] = 'mimi'
print(Cat.__dict__['name'])
>>>
TypeError: 'mappingproxy' object does not support item assignment
报错信息说明了__dict__
方法只能查看类内的属性,并不能进行增,删,改等操作。
2) 使用类名进行属性引用
print(Cat.name) # 使用类名.属性名来查看属性
print(Cat.action)
>>>
kitty
<function Cat.action at 0x000000000256EF28>
Cat.name = 'mimi' # 直接赋值修改属性
Cat.food = 'fish' # 直接赋值添加属性
Cat.hobby = 'bite'
Cat.toy = 'mouse'
print(Cat.name)
print(Cat.toy)
print(Cat.hobby)
>>>
mimi
mouse
bite
del Cat.hobby # 使用del语句删除属性
print(Cat.__dict__)
>>>
{'__module__': '__main__', 'name': 'mimi', 'action': <function Cat.action at 0x000000000256EF28>, '__dict__': <attribute '__dict__' of 'Cat' objects>, '__weakref__': <attribute '__weakref__' of 'Cat' objects>, '__doc__': None, 'food': 'fish', 'toy': 'mouse'}
类的调用和对象
类名() –> 生成对象
对象:类调用后就生成了一个对象,又可以称做实例化对象或者实例。
cat_obj = Cat()
print(cat_obj)
>>>
<__main__.Cat object at 0x0000000001FCDBA8>
可以看出已经生成了一个对象,但只是一个空对象,没有任何的属性和方法。
如何让一个空白的对象拥有一系列属性呢?
需要在类中定义一个构造函数:def __init__(self):
定义之后就可以通过给构造函数传递参数赋与空对象属性,这一步也可以称作对象的初始化。
slef : shelf 是类内方法传递的一个特殊参数,指向实例本身。当然可以不叫self,其他的变量名也行, 如this。不过一般情况下都是self,除非你‘异于常人’。
class Cat:
name = 'kitty'
def __init__(self, name, age, sex, food, toy):
self.name = name
self.age = age
self.sex = sex
self.food = food
self.toy = toy
def action(self):
pass
cat_obj = Cat('david', 0.5, 'girl', 'fish', 'mouse')
类属性可以使用类名.属性名进行增删改查,同理对象属性也可以。
# 对象属性的增删改查
print(cat_obj.name)
print(cat_obj.age) # 查看属性
>>>
david
0.5
cat_obj.name = 'mimi' # 修改属性
print(cat_obj.name)
>>>
mimi
cat_obj.hobby = 'bite' # 添加属性
print(cat_obj.__dict__)
>>>
{'name': 'mimi', 'age': 0.5, 'sex': 'girl', 'food': 'fish', 'toy': 'mouse', 'hobby': 'bite'}
del cat_obj.hobby # 删除属性
print(cat_obj.__dict__)
>>>
{'name': 'mimi', 'age': 0.5, 'sex': 'girl', 'food': 'fish', 'toy': 'mouse'}
# 同样使用对象名.__dict__方法也可以操作对象属性
# 对象名.__dict__方法 == 包含对象所有属性的字典
print(cat_obj.__dict__)
cat_obj.__dict__['age'] = 1 # 修改属性
print(cat_obj.__dict__['age']) # 查看属性
cat_obj.__dict__.pop('food') # 删除属性
print(cat_obj.__dict__)
被遗忘的action函数
怎么调用类中的方法呢?
就本篇来讲,可以用类调用不过需要传个对象,也可以用对象去调,用对象调用是最常见的调用方式, 至于其他方法的介绍可以查看面向对象封装篇。
class Cat:
name = 'mimi'
def __init__(self, name, age, hobby, toy):
self.n = name
self.a = age
self.h = hobby
self.t = toy
def action(self):
print('%s is jumping' % self.n)
cat_obj = Cat('kitty', 0.2, 'fish', 'mouse')
Cat.action(cat_obj)
cat_obj.action() # == Cat.action(cat_obj)
cat_obj.action() 怎么就能调用类中的方法呢?
一句话解释。 cat_obj.action()会被python自动映射为
Cat.action(cat_obj),意思就是用Cat类的action方法来处理cat_obj
名称空间
关于名称空间, 每个类创建的时候都会生成一个空间里面存放着类的属性和方法,当类实例化对象时,每个对象也会生成自己的空间,里面放着对象的属性和方法。可是
实例变量是每个实例唯一的数据,类变量是由类的所有实例共享的属性和方法。
也就是说类的就是实例的,实例的还是实例的。
例题:设计一个类,统计类被实例化的次数。
class Foo:
count = 0
def __init__(self):
Foo.count += 1 # 这里为什么要用Foo.count呢?
1)
f = Foo()
f1 = Foo()
f2 = Foo()
print(f.count)
print(f1.count)
print(f2.count)
>>>
3
3
3
2)
f = Foo()
print(f.count)
f1 = Foo()
print(f1.count)
f2 = Foo()
print(f2.count)
>>>
1
2
3
解答这个例题的关键点有两点:
1,当创建实例时,会自动调用__init__
函数, 并传进第一个特殊参数self。
2,如果要改变共享的属性,则需要改变类属性,而不是对象属性。