Python无处不对象,然而很多人并不清楚什么是对象,只知道编程的时候面向对象。
对象
Python中的对象的两个特征
- 属性
- 方法
self
对象的方法都会有一个self参数,如果把类比作图纸,那么由类实例化后的对象才是真正可以住的房子。根据一张图纸就可以设计出成千上万的房子,他们长的都差不多,但他们的主人都不同。每个人都只能会自己的家里,陪伴自己的孩子。。。所以self就相当于每个房子的门牌号,有了self,就可以轻松找到自己的房子
魔法方法(init)
Python的对象天生拥有一些神奇的方法,他们是面向对象的Python的一切。他们可以给你的类增加魔力的特殊方法,如果你的对象实现了这些方法中的某一个,那么这个方法就会在特殊的情况下被python所调用,而这一切都是自动发生的。
Python的这些方法总是被双下划线(__)所包围
init
通常把init成为构造方法,其魔力在于只要实例化一个对象,这个方法就会在对象被创建时自动调用。
实例化对象是可以传入参数的,这些参数会自动传入init()方法中,可以通过重写这个方法来自定义对象的初始化操作。
共有和私有
一般面向对象的编程语言都区分公有和私有的数据类型。
Python默认对象的属性和方法都是公开的,可以通过点操作符直接访问。
为了实现类似私有变量的特征,Python内部采用了一种叫name mangling(名字改编)的技术,在Python中定义私有变量只需要在变量名和函数名前加上“__”两个下划线,那么这个函数或者变量就是私有的了;
class Person:
__name = "private"
p = Person()
p.__name
# 输出是 报错
但是python的私有化是伪私有,通过“类名_变量名”即可方位双下划线开头的私有变量了
class Person:
__name = "private"
p = Person()
p._Person__name
# 输出是
继承
语法:
class 类名(被继承的类):
...
# 被继承的类称为父类、基类、超类;继承者称为子类,一个子类可以继承他的父类的任何属性和方法。
class Parent
def hello(self)
print("正在调用父类的方法")
class Children(Parent):
pass
child = Children()
child.hello()
子类构造器
- 调用未绑定的父类方法
class Children(Parent):
def __init__(self):
Parent.__init__(self)
- 使用super实现
class Children(Parent):
def __init__(self):
super().__init__()
多重继承
python还支持多重继承,就是可以同时删除多个父类的属性和方法
格式语法:
class 类名(父类1,父类2,…):
…
class Base01:
def foo01(self):
print("我是Base01中的foo01")
class Base02:
def foo02(self):
print("我是Base02中的foo02")
class Child(Base01,Base02):
pass
child = Child()
child.foo01()
child.foo02()
组合
Python提供了组合功能。
下面一个例子帮助我们理解什么是组合。
class Turtle:
def __init__(self,x):
self.num = x
class Fish:
def __init__(self,y):
self.num = y
class Pool():
def __init__(self,x,y):
self.trutle = Turtle(x)
self.fish = Fish(y)
def print_num(self):
print("池塘里一共有%d只鱼,%d只乌龟" % (self.fish.num,self.turtle.num))
pool = Pool(5,10)
pool.print_num()
类、类对象、实例对象
下面一段代码帮助我们理解上面的概念
class Test():
count = 0
a = Test()
b = Test()
c = Test()
print(a.count,b.count,c.count)
c.count += 10
print(a.count,b.count,c.count)
Test.count += 100
print(a.count,b.count,c.count)
# 输出是
0 0 0
0 0 10
100 100 10
分析: 对实例对象进行赋值之后,就相当于覆盖了类对象(Test)的count属性,如果没有覆盖,那么引用的是类对象的count
对象相关的BIF
issubclass(class,classinfo)
如果第一个参数(class)是第二个参数(classinfo)的一个子类,则返回True,否则返回False
- 一个类被认为是其自身的子类
- classinfo可以是对象组成的元组,只要class是其中任何一个候选类的子类,则返回True
- 在其他情况下,会抛出一个TypeError异常
isinstance(object,classinfo)
如果第一个参数(object)是第二个参数(classinfo)的实例对象,则返回True,否则返回False
1. 如果object是classinfo的子类的一个实例,也符合条件
2. 如果第一个参数不是对象,则永远返回False
3. classinfo可以是类对象组成的元组,只要object是其中任何一个候选对象的实例,则返回True
4. 如果第二个参数不是类或者类对象组成的元组,会抛出要给TypeError异常。
hasattr(object,name)
attr即attribute的缩写,属性的意思。测试一个对象里是否有指定的属性
第一个参数object是对象,第二个参数name是属性名
getattr(object,name[,default])
返回指定对象的属性值,如果不存在,则返回default的只;若没有default,则抛出AttributeError异常
setattr(object,name,value)
设置对象中指定属性的值,如果属性不存在,则新建属性
delattr(object,name)
删除指定属性的值,如果属性不存在则抛出AtrributeError异常
总结
为了避免对象命名的冲突,请大家遵守一些约定俗成的约定:
- 类的定义要“少吃多餐”,不要试图在要给类里边定义出所有能想到的特性和方法,应该利用继承和组合机制来进行扩展
- 用不同的词性命名,如属性名用名字、方法名用动词、并使用骆驼命名法