Python学习笔记六(面向对象,类,对象,魔法方法)

面向对象

什么是面向对象?

面向对象时一种思想,是基于面向过程的。

面向过程:面向过程需要程序员自己处理每一步的操作,就像是炒菜一样,需要准备好各种蔬菜,洗菜,切菜,打开煤气灶,放上锅,倒油。。。等等,直到菜出锅你都要知道,都要自己操作。

面向对象:如果用面向对象来描述炒菜应该是这样的。你要炒菜,但是你不会,你不会不要紧,你有钱是个壕,你找到一个厨师,对他说你要吃满汉全席。厨师走了,忙了一个中午,回来告诉你满汉全席做好了,可以用膳了。

从上面的两种炒菜方式可以看出来面向过程注重的内部细节(炒菜的整个流程),面向对象注重的是结果(菜炒出来了就行,怎么炒的我不关心)。

面向对象时基于面向过程的怎么理解?

还是用上面的炒菜来说明一下,现在我是壕,你是厨师. 因为我是壕, 我可以不会做菜。你是厨师,所以你必须会做菜。那么作为厨师这个对象, 你就需要知道怎么洗菜,切菜,打开煤气。。。。等等。

面向过程和面向对象是密不可分的。


光说面向对象,对象是啥?哪里来的?说到这就需要提到另一个概念

什么是类?

人以类聚,物以群分。类,类似,相似。程序中的类就是把一些具有相似功能的方法和属性放到一起,组成的一个小的功能集合,就叫做类,类是抽象的。

类的定义

定义格式

class 类名:  # class关键字
    方法列表

类的构成

类名
属性
方法

class People:  # 创建一个类
    pass

对象

什么是对象?

面向对象,在程序中都是先有类后有对象的,为什么呢?因为对象是类的一个具体存在。就像你,你是人类,是人类的一个具体的存在,具体的实例,所以一个类的具体的实例又叫做实例对象。同理,对象的方法以及属性,分别叫做实例方法以及实例属性。

创建实例对象

创建对象的过程:

class People:  # 首先创建一个类
    pass

# 创建类的一个实例,也就是对象,为了方便使用对象,将对象赋值给变量dragon_fang 
dragon_fang = People()  

对象的实例属性和实例方法

人类有一些特征,比如姓名、年龄、性别等。除了这些特征,人类还有很多行为,比如可以思考、可以奔跑、可以吃饭等。

这些描述性的特征就是一个对象的属性,而行为动作就是对象的方法。

class People:
    def cogitate(self):
        print("认真思考。。。")

    def run(self):
        print("可以跑步。。。")

    def eat(self):
        print("可以吃饭。。。")


dragon_fang = People()
dragon_fang.name = "DragonFang"
dragon_fang.age = 100
print("name:%s ,age:%d " % (dragon_fang.name, dragon_fang.age))

dragon_fang.cogitate()
dragon_fang.run()
dragon_fang.eat()

对象的属性和方法

通过 对象.属性 的方式可以直接为对象添加一个属性或者使用属性的值,对象.方法()的方式可以直接调用对象的方法。

self 形参,self 是一个形参,代表了调用方法的对象。虽然形参是可以任意命名的,但是为了规
范,这里建议使用self。

self 的使用

既然self 是实例对象的引用,name可不可以在实例方法中通过self 获取实例对象的实例属性?答案是可以的

class People:
    def cogitate(self):
        print("认真思考。。。")

    def run(self):
        print("可以跑步。。。")

    def eat(self):
        print("可以吃饭。。。")

    def show(self):  # 增加自我介绍方法
        print("name:%s ,age:%d " % (self.name, self.age))


dragon_fang = People()
dragon_fang.name = "DragonFang"
dragon_fang.age = 100

dragon_fang.cogitate()
dragon_fang.run()
dragon_fang.eat()
dragon_fang.show()

# 结果:
# 认真思考。。。
# 可以跑步。。。
# 可以吃饭。。。
# name:DragonFang ,age:100  # show()方法正常执行了

创建多个对象

class People:
    def cogitate(self):
        print("认真思考。。。")

    def run(self):
        print("可以跑步。。。")

    def eat(self):
        print("可以吃饭。。。")


dragon_fang = People()
dragon_fang.name = "DragonFang"
dragon_fang.age = 100
print("name:%s ,age:%d " % (dragon_fang.name, dragon_fang.age))

dragon_fang.cogitate()
dragon_fang.run()
dragon_fang.eat()

xiao_ming = People()  # 创建另一个People类的对象,赋值给xiao_ming

# 创建了xiao_ming 打印一下xiao_ming 的属性 
print("name:%s ,age:%d " % (xiao_ming.name, xiao_ming.age))

结果信息:
运行结果

22行报错,People 类没有属性 name 。创建第一个对象的时候添加了属性,dragon_fang 的属性可以正常使用, 创建第二个对象的时候说没有 name 属性,说明了什么? 说明对象的属性是各自独立的,不共享的。


魔法方法

魔法方法 __init__(self)

python官方提供了很多的魔法方法,魔法方法在恰当的时机,会自动执行。__init__(self) 就是其中之一,注意魔法方法两侧各有两条下划线 “_” ,__init__(self) 方法也是一样。(附官方说明:Called after the instance has been created (by new()), but before it is returned to the caller.)

__init__(self) 方法的作用是初始化。通过self引用的实力对象为每一个实例添加属性。因为self 引用了调用方法的实例对象,由此可以得出__init__(self) 方法的执行是在创建对象之后。

class People:
    def __init__(self):
        self.name = "DragonFang"
        self.age = 18

    def show(self):
        print("name:%s ,age:%d " % (self.name, self.age))


dragon_fang = People()
dragon_fang.show()

xiao_ming = People()
xiao_ming.show()

# 结果为:
# name:DragonFang ,age:18 
# name:DragonFang ,age:18 

怎么让每个实例对象的名字不相同呢?传参,通过给__init__(self)传参初始化每个实例对象的name、age。

class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age 

    def show(self):
        print("name:%s ,age:%d " % (self.name, self.age))


dragon_fang = People("DragonFang", 19)
dragon_fang.show()

xiao_ming = People("xiaoMing", 20)
xiao_ming.show()

# 结果为:
# name:DragonFang ,age:19 
# name:xiaoMing ,age:20 

魔法方法__Str__(self)

魔法方法__Str__(self) 的作用是打印对象的描述信息,必须有返回值,且返回值必须是字符串。(附官方说明:Called by str(object) and the built-in functions format() and print() to compute the “informal” or nicely printable string representation of an object. The return value must be a string object.)

class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        print("name:%s ,age:%d " % (self.name, self.age))

    def __str__(self):
        return "name:%s ,age:%d " % (self.name, self.age)


dragon_fang = People("DragonFang", 19)
dragon_fang.show()
print(dragon_fang)

# 结果为:
# name:DragonFang ,age:19 
# name:DragonFang ,age:19  

需要注意 __str__(self) 必须有返回值,而且返回值的类型必须是字符串类型,否则报错。
所以 __str__(self) 的作用一般是用来打印对象的描述信息。

魔法方法__del__(self)

魔法方法__del__(self) 当对象即将被销毁的时候执行。(附官方说明:Called when the instance is about to be destroyed)

什么情况下对象会被销毁?

  • 程序结束
  • 对象的所有引用被删除

__del__(self) 方法的作用,

  • 因为del(self) 方法在对象即将被销毁时调用,所以可以验证对象是否被销毁。
  • 因为del(self) 方法在对象即将被销毁时调用,所以也可以做一些其他操作,比如释放资源。

数据的保护

使用对象.属性可以在类的外部修改属性的值,但是这种修改方式不安全。

class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return "name:%s ,age:%d " % (self.name, self.age)


dragon_fang = People("DragonFang", 19)
dragon_fang.age = -500
print(dragon_fang)

# 结果为:
# name:DragonFang ,age:-500  # 这是传说中的向天再借五百年吗?

怎样确保数据的正确性呢?方法,通过方法设置可以确保数据的正确性。

class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return "name:%s ,age:%d " % (self.name, self.age)

    def set_age(self, new_age):
        if new_age >= 0:
            self.age = new_age
        print("数据不合法")


dragon_fang = People("DragonFang", 19)
dragon_fang.set_age(-500)
print(dragon_fang)

# 结果为:
# 数据不合法
# name:DragonFang ,age:19 

你可能会虽然通过方法确保了正确,但是依然可以通过对象.属性的方式设置属性的值,该怎么解决呢?私有,使用私有属性,私有属性配合方法使用能更好的保护数据的正确性。通过在属性前加两条下划线“_”的形式将公有属性变成私有属性

class People:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    def __str__(self):
        return "name:%s ,age:%d " % (self.name, self.__age)

    def set_age(self, new_age):
        if new_age >= 0:
            self.__age = new_age
        print("数据不合法")


dragon_fang = People("DragonFang", 19)
dragon_fang.set_age(-500)
print(dragon_fang)
dragon_fang.__age

Traceback (most recent call last):
File “E:/workspace/pycharm/pycharm/Demo.py”, line 18, in
dragon_fang.__age
AttributeError: ‘People’ object has no attribute ‘__age’
数据不合法
name:DragonFang ,age:19

报错了,说明在类外不能使用对象.属性名的方式访问私有属性。
不能访问私有属性,能不能访问私有方法?私有方法同样是通过增加两条下划线“_”的形式

class People:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    def __show(self):
        print("name:%s ,age:%d " % (self.name, self.__age))


dragon_fang = People("DragonFang", 19)
dragon_fang.__show()

Traceback (most recent call last):
File “E:/workspace/pycharm/pycharm/Demo.py”, line 11, in
dragon_fang.__show()
AttributeError: ‘People’ object has no attribute ‘__show’

报错,说明不能再类外通过对象.方法名() 的方式访问私有方法

伪私有

伪,假的。伪私有,不是真正的私有。python中没有真正意义上的私有都是伪私有。
为什么这么说?

class People:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    def __show(self):
        print("name:%s ,age:%d " % (self.name, self.__age))


dragon_fang = People("DragonFang", 19)
dragon_fang._People__show()

# 结果为:
# name:DragonFang ,age:19 

私有只是解释器在处理私有属性,私有方法的时候改变了属性 或者方法的名字,从而达到私有的目的。仅供了解,仅供了解,仅供了解。强烈不建议使用,强烈不建议使用,强烈不建议使用。


到此结   DragonFangQy   2018.4.10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值