前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Day8面向对象编程1/2

Day8面向对象编程1/2

作者头像
林清猫耳
发布2018-04-26 15:30:30
6390
发布2018-04-26 15:30:30
举报
文章被收录于专栏:我爱编程我爱编程
关于以下程序的笔记:

Python函数式编程2/3

代码语言:javascript
复制
def count():
    fs = []
    for i in range(1,4):
        def f():
            return i*i
        fs.append(f)
    return fs

f1,f2,f3 = count()

输出结果是

代码语言:javascript
复制
>>> f1()
9
>>> f2()
9
>>> f3()
9

首先,程序阅读出来f1,f2,f3=count(),然后要调用count()函数,首先读出他返回的是一个包含3个函数的列表fs,然后再去读取其中的3个函数。

代码语言:javascript
复制
for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)

这段代码中实际是先读取for,然后执行fs.append(f),因为f()函数没有参数,所以在连续为append写入3段f()以后,再执行f()的赋值或者计算,在f()函数中,由于已经执行完3次写入过程,因此return 后面的i已经变成了3

代码语言:javascript
复制
def count():
    fs = [3,4,5]
    return fs

f1,f2,f3 = count()
代码语言:javascript
复制
>>> f1
3
>>> f2
4
>>> f3
5 

这段代码调用count()函数,读出他返回的是一个包含三个元素的列表fs,然后读取其中的三个元素。

代码语言:javascript
复制
def maxx(my_list):
    if len(my_list) == 2:
        return my_list[0] if my_list[0] > my_list[1] else my_list[1]
    sub_max = maxx(my_list[1:])
    return my_list[0] if my_list[0] > sub_max else sub_max

类和实例

面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。

代码语言:javascript
复制
class Student(object):
    pass

定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的:

代码语言:javascript
复制
>>> bart = Student()
>>> bart
<__main__.Student object at 0x05B765D0>
>>> Student
<class '__main__.Student'>

变量bart指向的就是一个Student的实例,后面的0x05B765D0是内存地址,每个object的地址都不一样,而Student本身则是一个类。 由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的init方法,在创建实例的时候,就把name,score等属性绑上去:

代码语言:javascript
复制
class Student(object):

    def __init__(self, name, score):
        self.name = name
        self.score = score

__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。 有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:

代码语言:javascript
复制
>>> bart = Student('Bart Simpson', 59)
>>> bart.name
'Bart Simpson'
>>> bart.score
59
  • 类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;
  • 方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;
  • 通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。

访问限制

在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。 但是,从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的namescore属性:

代码语言:javascript
复制
>>> bart = Student('Bart Simpson', 59)
>>> bart.score
59
>>> bart.score = 99
>>> bart.score
99

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,所以,我们把Student类改一改:

代码语言:javascript
复制
class Student(object):

    def __init__(self, name, score):
        self.__name = name
        self.__score = score

    def print_score(self):
        print('%s: %s' % (self.__name, self.__score))

改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name和实例变量.__score了:

代码语言:javascript
复制
>>> bart = Student('Bart Simpson', 59)
>>> bart.__name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'

这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。 如果外部代码要获取name和score怎么办?可以给Student类增加get_nameget_score这样的方法:

代码语言:javascript
复制
class Student(object):
    ...

    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score

如果又要允许外部代码修改score怎么办?可以再给Student类增加set_score方法:

代码语言:javascript
复制
class Student(object):
    ...

    def set_score(self, score):
        self.__score = score

注意下面的这种错误写法

代码语言:javascript
复制
>>> bart = Student('Bart Simpson', 59)
>>> bart.get_name()
'Bart Simpson'
>>> bart.__name = 'New Name' # 设置__name变量!
>>> bart.__name
'New Name'

表面上看,外部代码“成功”地设置了__name变量,但实际上这个__name变量和class内部的__name变量不是一个变量!内部的__name变量已经被Python解释器自动改成了_Student__name,而外部代码给bart新增了一个__name变量。不信试试:

代码语言:javascript
复制
>>> bart.get_name() # get_name()内部返回self.__name
'Bart Simpson'
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.03.28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于以下程序的笔记:
  • 类和实例
  • 访问限制
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档