python学习:从新手到专家阅读笔记(4)

在python中,可以使用class关键字定义类

class Person:
    def setName(self, name):
        self.name = name

    def getName(self):
        return self.name

    def greet(self):
        print "hello from " + self.name

person = Person()
person.setName("jzj")
person.greet()

 

这里,可以看出:

    1. 定义类时,类的成员属性可以不用声明,直接拿过来用,比如self.name

    2. 定义类成员方法时,必须作为第一个参数显式声明self参数,在方法内部引用时也是显式引用这个self参数,而在调用这个类的方法时,无需显式添加这个参数了,比如greet方法,定义时是greet(self),使用时直接person.greet()就ok了。

    3. 方法和属性的引用与module中函数的引用是一样的,都是用"."引用。这一点看着舒服,输入方便,比lua的":"方便。

 

比较起来,lua中变量默认都是global的,以及使用":"分隔这些,用起来就觉得不爽,用lua写大型程序自然也就不容易了。

 

函数和方法

在所有面向对象语言中,函数和方法的区别,就是方法的第一个参数是对象本身(this或self)。

在lua中,obj.method只是obj["method"]的一个syntax sugar,所以对于一个方法m1,只要obj1.method = m1, obj2.method=m1,则obj1.method()和obj2.method()返回值都是一样的。就是说,方法的执行和方法从哪个对象中的引用调用过来是没有关系的:

c = {name="cc"}
function c:m1()
    print("hello from m1 of " .. c.name)
end

a={}
b={}
a.m = c.m1
b.m = c.m1
a.m()  -- hello from m1 of cc
b.m()  -- hello from m1 of cc

 

而在javascript中,情况有所不同,使用哪个对象去调用方法,结果会不一样,这与面向对象的理念更加接近,但与函数作为“第一阶级”元素的函数式编程理念却有些背离:

<html>
    <head> <title> test </title> </head>
    <body>
        <script>
            function MyClass(name)
            {
                this.name = name
                this.hello = function()
                {
                    alert("hello from " + this.name)
                }
            }

            o1 = new MyClass("o1")
            o2 = new MyClass("o2")
            o1.hello() // hello from o1
            o2.hello() // hello from o2
            o2.hello = o1.hello
            o2.hello() // hello from o2
        </script>
    </body>
</html>

 

python中的方法,是更加面向对象一些呢,还是更加函数式一些呢?测试一下:

 

class Person:
    def setName(self, name):
        self.name = name

    def greet(self):
        print "person hello from " + self.name

class Animal:
    def setType(self, type):
        self.type = type

    def shout(self):
        print "animal shout from " + self.type

#if __module__ == '__main__':
person = Person()
person.setName("jzj")
person.greet()     # person hello from jzj

animal = Animal()
animal.setType("dog")
animal.shout()     # animal shout from dog

person.greet = animal.shout

person.greet()     # animal shout from dog

a2 = Animal()
a2.setType("cat")
a2.shout()         # animal shout from cat
a2.shout = animal.shout
a2.shout()         # animal shout from dog

 

可以看出,python的方法,独立性更强一些,更加函数式一些,只要定义时确定了是什么,不管从哪里调用,就是什么,不会随着调用位置的改变而改变,与调用对象的关系不大。

 

也可以看出,对象的方法,在对象被定义时就已经确定了,可以知道其self是谁了,这个方法是一个独一无二的实例,不会存在着多个对象共用一个方法的问题。这样会造成方法代码存储的浪费,但灵活性更强。当然,在实际实现中,可以通过一个中间层“function”对象,来解耦真正的代码和它的绑定数据,从而增加灵活性的同时,不会造成方法代码存储的浪费。lua中的function就是这么做的。

 

在python中,方法也叫“绑定方法”,就是说,方法在定义时已经绑定了某个对象,后续对它的调用,无论是使用方法调用方式obj.method(),还是使用函数调用方式func(),效果都是一样的。

 

方法访问权限

在python中,没有private、protected、public等成员修饰属性,要让一个方法外部不可见,只能内部可见,方法名字前面可以加上两个下划线,比如:__myprivatemethod。实际上,凡是带有双下划线的方法,python会添加前缀_Classname,所以类Person的私有方法__privatemethod,实际上仍然可以这样访问_Person__privatemethod,尽管这种访问方式不标准。

 

带单下划线的话,from module import *时,不会把这些方法导入。实际上,在使用*导入一个module中的名字时,所有以下划线开头的(单下划线或多下划线)名字都不会导入,不论方法名还是变量名还是类名

 

类作用域

在类定义内部,实际上是开始了一个新的作用域(scope),在这个作用域中可以执行任何语句,包括print,赋值语句等等,def实际上是定义函数变量。

另外,dict虽然可以用dict['key']来访问其内部以字符串为key的项,但不能使用dict.key的方式来访问。这一点不如lua方便。

在类作用域中定义的成员都是类级别的成员,在类的所有成员对象中共享,而在self范围内定义的就是self的成员,只有具体对象使用。

 

异常

异常与其他语言的异常类似,语法如下:

try:

except xxx:

else:

finally:

 

构造函数

python中,所有以__开头并以__结尾的名字都有特殊含义,比如类中__init__是构造函数,而__del__是析构函数。其中__init__用得最多。

 

lua中,访问一个不存在的变量返回none,而python中,访问一个不存在的变量会产生异常。相对而言,python的这种做法更好,更容易发现错误。

 

在创建了一个新的对象后,对象中的方法都是绑定了的。如果使用类名直接引用类中的方法,如Person.greet,此时这个方法是没有绑定的,需要显式指定self对象,比如person = Person(),person.greet(), Person.greet(person)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值