人工智能之Python15 面向对象编程

Python无处不对象,然而很多人并不清楚什么是对象,只知道编程的时候面向对象。

对象

Python中的对象的两个特征

  1. 属性
  2. 方法

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()

子类构造器

  1. 调用未绑定的父类方法
class Children(Parent):
    def __init__(self):
        Parent.__init__(self)
  1. 使用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

  1. 一个类被认为是其自身的子类
  2. classinfo可以是对象组成的元组,只要class是其中任何一个候选类的子类,则返回True
  3. 在其他情况下,会抛出一个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异常

总结

为了避免对象命名的冲突,请大家遵守一些约定俗成的约定:

  • 类的定义要“少吃多餐”,不要试图在要给类里边定义出所有能想到的特性和方法,应该利用继承和组合机制来进行扩展
  • 用不同的词性命名,如属性名用名字、方法名用动词、并使用骆驼命名法

猜你喜欢

转载自blog.csdn.net/u012806787/article/details/79317512