面向对象编程概述、实例对象属性、类对象属性
本文是来源于上雷俊丽老师python课的课件。
1.面向对象编程概述
面向对象编程(OOP), 是一种编程方式,这种编程方式需要使用“对象”来实现。
对象的特征:
- 世间万物皆对象。
- 每个对象都是唯一的。
- 对象具有属性和行为。
- 对象具有状态。
- 对象分为类对象和实例对象两大类。
面向对象编程的大体步骤:
- 抽象出类对象。
- 抽象出类对象的属性。
- 抽象出类对象的行为(方法)。
- 根据类对象创建实例对象。
- 通过实例对象访问属性和方法。
定义类对象的语法格式:
class name(object):
#property and function.
其中:
- 类名由一个或多个单词组合而成,每个单词的首字母大写且其余字母全部小写,例如:SomeClass。
- (object)表示该类对象继承自Python内置的类对象object,Python中所有的类对象都继承自一个统一的基类:object。
实例化:
cat = Cat('傻猫', 'wang', 1, 'good')
属性:
- 为了在创建实例对象后对其进行初始化(例如:给实例对象绑定一些属性),可以在类对象中定义一个名为
__init__的特殊方法(以双下划线__开头和结尾的方法)。这样,创建实例对象后就会自动调用特殊方法__init__。 - 如果没有定义特殊方法
__init__, 或者定义了特殊方法__init__但是没有定义除self之外的形参,那么根据类对象创建实例对象时就不需要传入实参。 - 如果在类对象中定义了特殊方法
__init__, 那么对于“类名([实参])”,会执行两大步:- 创建实例对象
- 会自动调暗勇创建的实例对象的特殊方法
__init__(创建的实例对象会作为实参被自动传递给特殊方法__init__的第一个形参self)。
类的方法与函数的区别:
方法就是定义在类对象中的函数。方法与函数的区别在于:
- 定义方法时,方法的第一个形参表示调用该方法的实例对象,第一个形参的名称通常时self,也可以是其他名称。
- 调用方法时,系统自动将调用该方法的实例对象作为实参传递给第一个形参。第一个实参会传递给第二个形参,第二个实参会传递给第三形参,依次类推。
根据类对象创建实例对象的语法格式为:
类名([实参])
class Cat(object):
def __init__(self, breed, name, age, health):
self.breed = breed
self.name = name
self.age = age
self.health = health
#猫具有的属性:品质拍卖会、昵称、年龄、健康状况
#self指实例化的对象,将属性赋给实例化的对象
#self表示自己,可以取其他的名字,但一般不取其他名字
#实例对象取cls
#后面四个都需要赋值,self不需要传参数
def run(self):
print('run')
def miao(self):
print('miao')
def eat(self):
print('eat')
#实例对象公共的行为方法定义为函数。
#猫将原有的行为:跑、叫、吃
#实例化
cat = Cat('傻猫', 'wang', 1, 'good')
#查看对象的属性
print(cat.breed)
print(cat.name)
print(cat.age)
print(cat.health)
[out]
傻猫
wang
1
good
#调用方法(类里面定义的函数)
cat.run()
cat.miao()
cat.eat()
[out]
run
miao
eat
2.实例对象属性
实例属性:
实例属性指的是实例对象所绑定的属性。
绑定实例属性(给实例对象绑定属性)的方式有两种:
- 在类对象的内部(方法中)
语法格式:self.property = value
推荐在特殊方法__init__中进行绑定,这样,在创建实例对象后就会自动调用特殊方法__init__对实例对象进行初始化,从而绑定实例属性。如果在其他方法中进行绑定,可能需要手动调用方法后才会绑定。 - 在类对象的外部
Python时动态语言,所以,在实例对象创建之后,可以对其动态地绑定属性。
语法格式:实例对象.属性名 = 属性值
如果指定名称地实例属性已经存在,则是对实例属性进行修改。
访问实例属性地方式有两种:
- 在类对象的内部(方法中)
语法格式:self.property - 在类对象的外部
语法格式:实例对象.属性名
之所以添加前缀“self”或“实例对象”,是为了表明实例属性被哪个实例对象所绑定。
class MyClass(object):
def __init__(self):
#在类对象的内部(方法中)绑定实例属性
self.ia1 = 18
def do_sth1(self):
#在类对象的内部(方法中)访问实例属性
print(self.ia1)
def do_sth2(self):
print(self.ia2)
def do_another(self):
#在类对象的内部(方法中)绑定实例属性
self.ia2 = 56
def do_sth3(self):
print(self.ia3)
mc = MyClass()
mc.do_sth1()
[out]
18
mc.do_another()
mc.do_sth2()
[out]
56
#在类的外部定义属性
mc.ia3 = 66
mc.do_sth3()
[out]
66
mc2 = MyClass()
print(mc2.ia3)
[out]
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-34-85d88b23cdb9> in <module>
1 mc2 = MyClass()
----> 2 print(mc2.ia3)
3 #同一个类对象的。。。(除非是公共属性)
AttributeError: 'MyClass' object has no attribute 'ia3'
同一个类对象的不同实例对象所绑定的实例属性是相互独立的。也就是说,给一个实例对象所绑定的实例属性,对于另外一个实例对象是不起作用的。
实例对象.__dict__
可获得该实例对象所绑定的所有属性及其值的字典。
#实例对象.__dict__
#可获得该实例对象所绑定的所有属性及其值的字典
mc.__dict__
mc2.__dict__
[out]
{'ia1': 18}
[out]
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'do_another',
'do_sth1',
'do_sth2',
'do_sth3',
'ia1']
3.类对象属性
类属性
类属性指的是类对象所绑定的属性。
绑定类属性(给类对象绑定属性)的方式有两种:
- 在类对象的内部(方法外)
语法格式:属性名 = 属性值 - 在类对象的外部
Python是动态语言,所以在类对象创建之后,可以对其动态地绑定属性。
语法格式:类对象.属性名 = 属性值 如果指定名称的类属性已经存在,则是对类属性进行修改。
访问类属性的方式有两种:
- 在类对象的内部(方法中)
语法格式:类对象.属性名 - 在类对象的外部
语法格式:类对象.属性名 或 实例对象.属性名
类对象的所有实例对象都有一个指向类对象的指针,所以类对象的所有实例对象都可以访问类属性。
之所以添加前缀“类对象”,是为了表明类属性被哪个类对象所绑定。
class MyClass(object):
cal = 66
def do_sth(self):
#在类对象内部(方法外)绑定属性
cal = 66
def do_sth(self):
#在类对象内部(方法中)访问类属性。
print(MyClass.cal)
MyClass.cal
[out]
66
mc = MyClass()
mc.cal
[out]
66
mc.do_sth()
[out]
66
#在类对象的外部绑定类属性
MyClass.ca2 = 88
print(MyClass.ca2)
[out]
88
print(mc.ca2)
[out]
88
#在类对象的外部修改类属性
MyClass.ca2 = 99
print(MyClass.ca2)
[out]
99
print(mc.ca2)
[out]
99
class MyClass(object):
#在类对象内部(方法外)绑定类属性
cal = 66
def do_sth(self):
#在类对象内部(方法中)访问类属性
print(MyClass.cal)
def do_another(self):
#在类对象内部(方法中)访问类属性
print(MyClass.ca2)
mc = MyClass()
#在类对象外部调用类方法,使得在类对象内部(方法中)访问类属性
mc.do_another()
[out]
99
访问实例属性和类属性都可以通过“实例对象.属性名”的方式。当通过“实例对象.属性名”的方式访问属性时,会先查找制定的实例对象中有没有指定名称的实例属性,如果没有,在查找对应的类对象中有没有制定名称的类属性。所以,当通过“实例对象.属性名”的方式访问属性时,如果实例属性和类属性同名,实例属性会屏蔽掉类属性。
当通过“实例对象.属性名 = 属性值”的方式绑定属性时,这里的属性指标是实例属性(因为类属性没有这样的绑定方式),所以之会查找制定的实例对象有没有绑定制定名称的实例属性,如果没有则进行绑定,如果已经绑定了,则对属性值进行修改。
class Person(object):
age = 18
p = Person()
#在实例对象p中没有找到名为age的实例属性,然后在类对象Person中找到了名为age的类属性
print(p.age)
[out]
18
#打印名为age的类属性
print(Person.age)
p.age = 19
print(p.age)
[out]: 19
print(Person.age)
[out]: 18
#删除实例对象p绑定的实例属性
del p.age
print(p.age)
[out]: 18
p1 = Person()
p2 = Person()
p1.age += 2
print(Person.age)
print(p1.age)
print(p2.age)
[out]: 18
20
18
Person.age += 3
print(Person.age)
print(p1.age)
print(p2.age)
[out]: 21
20
21