zoukankan      html  css  js  c++  java
  • Python动态语言理解

     

    1. 动态语言的定义

    动态编程语言 是 高级程序设计语言 的一个类别,在计算机科学领域已被广泛应用。它是一类 在运行时可以改变其结构的语言 :例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。动态语言目前非常具有活力。例如JavaScript便是一个动态语言,除此之外如 PHP 、 Ruby 、 Python 等也都属于动态语言,而 C 、 C++ 、Java等语言则不属于动态语言。

    2. 运行的过程中给对象绑定(添加)属性

    >>> class Person(object):
        def __init__(self, name = None, age = None):
            self.name = name
            self.age = age
    
    
    >>> P = Person("小明", "24")
    >>>

    在这里,我们定义了1个类Person,在这个类里,定义了两个初始属性name和age,但是人还有性别啊!如果这个类不是你写的是不是你会尝试访问性别这个属性呢?

    >>> P.sex = "male"
    >>> P.sex
    'male'
    >>>

    这时候就发现问题了,我们定义的类里面没有sex这个属性啊!怎么回事呢? 这就是动态语言的魅力和坑! 这里 实际上就是 动态给实例绑定属性!

    3. 运行的过程中给类绑定(添加)属性

    >>> P1 = Person("小崔", "27")
    >>> P1.sex
    
    Traceback (most recent call last):
      File "<pyshell#21>", line 1, in <module>
        P1.sex
    AttributeError: Person instance has no attribute 'sex'
    >>>

    我们尝试打印P1.sex,发现报错,P1没有sex这个属性!—- 给P这个实例绑定属性对P1这个实例不起作用! 那我们要给所有的Person的实例加上 sex属性怎么办呢? 答案就是直接给Person绑定属性!

    
    >>>> Person.sex = None #给类Person添加一个属性
    >>> P1 = Person("xiaoke", "25")
    >>> print(P1.sex) #如果P1这个实例对象中没有sex属性的话,那么就会访问它的类属性
    None #可以看到没有出现异常
    >>>

    4. 运行的过程中给类绑定(添加)方法

    我们直接给Person绑定sex这个属性,重新实例化P1后,P1就有sex这个属性了! 那么function呢?怎么绑定?

    >>> class Person(object):
        def __init__(self, name = None, age = None):
            self.name = name
            self.age = age
        def eat(self):
            print("eat food")
    
    
    >>> def run(self, speed):
        print("%s在移动, 速度是 %d km/h"%(self.name, speed))
    
    
    >>> P = Person("老王", 24)
    >>> P.eat()
    eat food
    >>> 
    >>> P.run()
    Traceback (most recent call last):
      File "<pyshell#5>", line 1, in <module>
        P.run()
    AttributeError: Person instance has no attribute 'run'
    >>>
    >>>
    >>> import types
    >>> P.run = types.MethodType(run, P)
    >>> P.run(180)
    老王在移动,速度是 180 km/h

    既然给类添加方法,是使用类名.方法名 = xxxx,那么给对象添加一个方法也是类似的对象.方法名 = xxxx

    完整的代码如下:

    
    import types
    
    #定义了一个类
    class Person(object):
        num = 0
        def __init__(self, name = None, age = None):
            self.name = name
            self.age = age
        def eat(self):
            print("eat food")
    
    #定义一个实例方法
    def run(self, speed):
        print("%s在移动, 速度是 %d km/h"%(self.name, speed))
    
    #定义一个类方法
    @classmethod
    def testClass(cls):
        cls.num = 100
    
    #定义一个静态方法
    @staticmethod
    def testStatic():
        print("---static method----")
    
    #创建一个实例对象
    P = Person("老王", 24)
    #调用在class中的方法
    P.eat()
    
    #给这个对象添加实例方法
    P.run = types.MethodType(run, P)
    #调用实例方法
    P.run(180)
    
    #给Person类绑定类方法
    Person.testClass = testClass
    #调用类方法
    print(Person.num)
    Person.testClass()
    print(Person.num)
    
    #给Person类绑定静态方法
    Person.testStatic = testStatic
    #调用静态方法
    Person.testStatic()

    以上代码运行结果:

    eat food
    老王在移动, 速度是 180 km/h
    0
    100
    ---static method----

    5. 运行的过程中删除属性、方法

    删除的方法:

    del 对象.属性名 
    delattr(对象, “属性名”) 
    通过以上例子可以得出一个结论:相对于动态语言,静态语言具有严谨性!所以,玩动态语言的时候,小心动态的坑!

    那么怎么避免这种情况呢? 请使用slots,

    6._slots_

    现在我们终于明白了,动态语言与静态语言的不同

    动态语言:可以在运行的过程中,修改代码

    静态语言:编译时已经确定好代码,运行过程中不能修改

    如果我们想要限制实例的属性怎么办?比如,只允许对Person实例添加name和age属性。

    为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的_slots_变量,来限制该class实例能添加的属性:

    >>> class Person(object):
        __slots__ = ("name", "age")
    
    >>> P = Person()
    >>> P.name = "老王"
    >>> P.age = 20
    >>> P.score = 200
    Traceback (most recent call last):
      File "<pyshell#3>", line 1, in <module>
    AttributeError: Person instance has no attribute 'score'
    >>>

    注意: 
    使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的

    class Test(Person):
          pass
    
    t = Test()
    
    t.score = 100

    7.私有化

    xx: 公有变量
    _x: 单前置下划线,私有化属性或方法,from somemodule import *禁止导入,类对象和子类可以访问
    __xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到)
    __xx__:双前后下划线,用户名字空间的魔法对象或属性。例如:__init__ , __ 不要自己发明这样的名字
    xx_:单后置下划线,用于避免与Python关键词的冲突
    
    通过name mangling(名字重整(目的就是以防子类意外重写基类的方法或者属性)如:_Class__object)机制就可以访问private了。

    总结: 
    父类中属性名为__名字的,子类不继承,子类不能访问 
    如果在子类中向__名字赋值,那么会在子类中定义的一个与父类相同名字的属性 
    _名的变量、函数、类在使用from xxx import *时都不会被导入

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014745194/article/details/73409804
  • 相关阅读:
    219. Contains Duplicate II
    189. Rotate Array
    169. Majority Element
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    119. Pascal's Triangle II
    118. Pascal's Triangle
    88. Merge Sorted Array
    53. Maximum Subarray
    CodeForces 359D Pair of Numbers (暴力)
  • 原文地址:https://www.cnblogs.com/xc1234/p/9165845.html
Copyright © 2011-2022 走看看