-关注的是对象,而不关注过程
-对于面向对象的语言来说,一切都是对象
-例子:孩他妈叫孩子起床(不需要再指挥妈妈的起床到送孩子上学之间的每个步骤了)
-面向对象的编程思想,将所有的功能统一保存到对应的对象中
比如,妈妈的功能保存到妈妈的对象中,孩子的功能保存到孩子的对象中
要使用某个功能,直接找到对应的对象即可
我们当前所学的对象都是Python的内置对象
但是内置对象并不能满足我们所有的需求,所以我们在开发中经常需要自定义一些对象
类是对象的图纸,在程序中要根据类来创建对象
我们也称对象时类的实例(instance)
通过同一个类创建的多个对象,我们称这些对象是一类对象
像int()、float()、str()、list()、dict() .......这些都是类
我们自定义的类都需要使用大写字母开头,使用驼峰命名法来对类命名
类也是一个对象。
类就是一个用来创建对象的对象。
类是type类型的对象,定义类实际上就是定义了一个type类型的对象。
a = int(10) # 创建一个int类型的实例 等价于 a = 10
b = str('abc') # 创建一个str类型的实例 等价于 a ='abc'
print(a, type(a)) # 10
print(b, type(b)) # 10
1.创建一个变量mc
2.在内存中创建一个新对象
3.__init__(self)方法执行
4.将对象的id赋值给变量
#定义一个MyClass类
class MyClass:
pass
print(MyClass) #
# 使用MyClass创建一个对象
mc = MyClass() # mc是MyClass的实例
mc2 = MyClass()
mc3 = MyClass()
# mc mc2 mc3 都是MyClass的实例。它们都是同一类对象
# isinstance()用来检查一个对象是否是一个类的实例
result = isinstance(mc, MyClass) # True
print(result)
print(mc, type(mc))
# 现在我们通过Myclass这个类创建的对象都是一个空对象。
# 也就是对象中实际上什么都没有,就相当于是一个空盒子
# 可以向对象中添加变量,对象中的变量称为属性
# 语法:对象.属性 = 属性值
mc.name = 'swk'
print(mc.name)
- 类和对象都是对现实生活中事物或程序中的内容的抽象
- 实际上所有的事物都由两部分构成:
1.数据(属性)
2.行为(方法)
- 在类的代码块中我们可以定义变量和函数
变量会成为该实例的公共属性,所有的该类实例都可以通过对象.属性名 的形式访问
函数会成为该类实例的公共方法, 所有该类实例都可以通过对象.方法名() 的形式调用方法
- 注意:
方法调用时,第一个参数由解析器自动传递,所以定义方法时,至少要定义一个形参!
-实例为什么可以访问到类中的属性和方法
类中定义的属性和方法都是公共的,任何该类的实例都可以访问
- 属性和方法查找的流程
当我们调用一个对象的属性时,解析器会先在当前对象中寻找是否含有该属性,
如果有,则直接返回当前的对象的属性值
如果没有,则去当前对象的类对象中去寻找,如果有则返回类对象的属性值,
如果上述两个地方都没有,则报错!
- 类对象和实例对象中都可以保存属性(方法)
-如果这个属性(方法)是所有的实例共享的,则应该将其保存到类对象中
-如果这个属性(方法)是某个实例独有,则应该将其保存到实例对象中
- 一般情况下,属性保存到实例对象中
而方法需要保存到类对象中
# 尝试定义一个表示人的类
class Person:
# 在类的代码块中,我们可以定义变量和函数
# 在类中我们所定义的变量,将会成为所有的实例的公共属性
# 所有实例都可以访问这些变量
name = 'swk' # 公共属性 所有的实例都可以访问
# 在这个类中也可以定义函数,类中的定义的函数,我们称为方法
# 这些方法可以通过该类的实例来访问
def say_hello(self): # 必须要由至少一个形参,否则报错,建议第一个形参命名为self
# 方法每次被被调用时,解析器都会自动传递第一个实参
# 第一个参数,就是调用方法的对象本身
# 如果是p1调的,则第一个参数就是p1对象
# 如果是p2调的,则第一个参数就是p2对象
# 一般我么都会将这个参数命名为self
print('你好! 我是 %s' % self.name)
# print('你好! 我是 %s' %name)#不能这样写,因为在方法中不能直接访问类中的属性
# 创建Person的实例
p1 = Person()
p2 = Person()
print(p1.name) # swk #表示读取p1对象的name,如果p1对象有此属性,则返回p1对象的此属性值,如果没有此属性,就去类对象中去找此属性,如果类对象中有,则返回类对象中的此公共属性的值。
print(p2.name) # swk
print("----------------")
p1.name = 'zbj' # 表示修改p1对象的name属性,如果p1对象没有此属性,不会去类对象中去找此属性,而是在p1对象中添加此属性,并赋值。所以不是修改的类对象中的公共属性。
print(p1.name) # zbj 会变
print(p2.name) # swk 不变
print("================")
Person.name = 'swj' # 通过类对象访问name,并赋值,若类对象中没有此属性,就添加此属性。若有,则修改公共的此属性。
print(p1.name) # zbj 不会变,因为p1对象中,已经添加了此name属性,就不会再访问类对象中的此公共属性。
print(p2.name) # swj 会变 #p2对象中没有此属性,访问的还是类对象中的公共属性
print("*****************")
# 调用方法,对象.方法名()
# 方法调用和函数调用的区别
# 如果是函数调用,则调用时传几个参数,就会有几个实参
# 但是如果是方法调用,默认传递一个参数,所以方法中至少要定义一个形参。
p1.say_hello() # 默认会传递当前实例对象作为第一个实参,所以对应的say_hello方法中至少定义一个形参来接收。
p2.say_hello() # 同上
# 下面这两种调用方式等价于上面的方式
# Person.say_hello(p1)
# Person.say_hello(p2)
Person.say_hello(Person) # 如果使用类对象调用,必须显示的传递类对象或实例对象作为第一个参数
在类的定义中添加以下代码:
# init 会在对象创建以后离开执行
# init 可以用来向新创建的对象中初始化属性
# 调用类创建对象时,类后边的所有参数都会依次传递到init()中
def __init__(self, name):
# print(self) #key比较下创建的实例对象的地址和这个self的是否相同,这里是相同的,self就是当前实例对象
# 同self向新建的对象中初始化属性
self.name = name
#那么在创建类的实例对象时,就必须传递name形参对应的实参,否则报错。
# p3 = Person() #报错
p3 = Person('swk')