聊聊python

python面向对象编程(2)

2017-10-09  本文已影响11人  疾风先生
类编写细节

1.class 语句

class语句细节

class语句如何得到命名空间

class语句一般形式

## 根据上述所言,className是类对象的一个引用
class className(superclass1,superclass2,...):          
    '''
        定义类属性,属于所有实例的共享数据,通过类语句下进行定义和创建
    '''
    class_attr = value 
    
    
    '''
        定义实例方法以及实例属性
    '''
    def method(self,data):      ## 定义实例方法
        self.attr = data        ## 设置实例属性,通过带有self的方法来分配属性信息

2.方法

实例方法对象调用等价于类方法函数调用

## python自动将实例方法的调用自动转成类方法函数,并传递实例对象作为第一个参数传递
class Person:
    def study(self,name):
        print("%s study method in for %s" % (name,self.__class__.__name__)

>>> p = Person()
>>> p.study("keithl")
keithl study method in for Person

>>> Person.study(p,"keithl")
keithl study method in for Person

## instance.method(arg1,arg2,...) == class.method(instance,arg1,arg2,...)

调用超类的构造函数__init__方法

class Person:
    def __init__(self):
        print("call person init ....")

class Student(Person):
    pass
        
>>> s = Student()               ## 创建子类时会调用父类构造函数,原因是子类没有定义自己的构造函数
call person init ....

## 为子类增加构造函数
class Student(Person):
    def __init__(self):
        print("call student init ....")

>>> s = Student()               ## 只输出子类的__init__方法,并没有调用父类方法,原因在于python是根据命名空间来执行调用方法
call student init ....

## 若要调用父类构造方法则必须显示进行调用
class Student(Person):
    """
        必须在子类构造函数中显式调用父类的构造函数,并传递子类的self引用
    """
    def __init__(self):
        print("call student init start....")
        Person.__init__(self)              
        print("call student init end....")

>>> s = Student()               
call student init start....
call person init ....
call student init end....

静态方法

## person.py
class Person:
    num = 1
    """
        定义一个没有带参数的普通方法
    """
    def printNum():
        Person.num += 1
        print("the number is %s" % Person.num)
    
    printNum = staticmethod(printNum)                   ## 声明为静态方法
    
    """
        定义一个带参数的普通方法,此参数为类对象参数
    """
    def clsPrintNum(cls):
        Person.num += 1
        print("the number is %s" % Person.num)         

    clsPrintNum = classmethod(clsPrintNum)              ## 声明为类方法

>>> Person.printNum()
the number is 2

>>> Person.clsPrintNum()
the number is 3

## person.py 使用装饰器来声明静态或类方法
class Person:
    num = 1
    
    @staticmethod
    def printNum():
        Person.num += 1
        print("the number is %s" % Person.num)

    @classmethod
    def clsPrintNum(cls):
        Person.num += 1
        print("the number is %s" % Person.num)

静态方法、类方法与实例方法

class Person:

    @staticmethod
    def static_method():
        print("static method ...")

    @classmethod
    def class_method(cls):
        print("class method ....")

    def instance_method(self):
        print("instance method ...")

    '''
        python3.x可以调用下面的函数,可以说是静态方法,但严格意义上是属于类的一个行为方法,但是python2.x无法该方法
    '''
    def fn():
        print("just a fn,if py3.x,it is static method")

## 总结:
1)在类中定义方法一定要规范化,明确是静态方法还是类方法抑或是实例方法
2)避免使用最后一种方式在类中定义方法

3.命名空间与作用域

无点号运算的变量名称

X = "global X"
def enclosing_fn():
    ## global X             
    X = "enclosing fn"      ## 创建当前enclosing_fn的本地变量X如果没有声明为全局变量的话
X = "global X"
def enclosing_fn():
    X = "enclosing fn"      ## 如果注释此行,将打印全局的变量X
    print(X)
    def local_x()
        x = "local x"       ## 如果仅注释此行,将会打印嵌套的变量X
        print(x)
    local_x()

点号的属性变量名称

>>> p = Person()

## 在对象实例的命名空间创建或更改属性名称name
p.name = "keithl"       ## 并无进行变量名称的搜索

## 在类的命名空间中创建或更改属性名称name
Person.name = "keithl"  ## 并无进行变量名称的搜索
>>> p = Person()
>>> p.name          ## 从对象命名空间开始按照继承树来搜索
>>> Person.name     ## 从类的命名空间开始按照继承树来搜索

命名空间字典

类与模块的关系总结

上一篇 下一篇

猜你喜欢

热点阅读