一、动态语言与静态语言

1.1 静态语言特点:

a. 在定义变量时需要指定变量的类型,根据指定的类型来确定变量所占的内存空间

b. 需要经过编译才能运行

c. 在代码编译后,运行过程不能对代码进行操作

d. 常见的静态语言:C、C++、Java等

1.2 动态语言的特点:

a. 不需要经过编译,而是由解释器程序来解释执行代码

b. 在代码运行过程中,可以动态地对代码进行操作

c. 常见的动态语言:Python、PHP、Ruby、JavaScript等

1.3 优缺点比较:

a. 静态语言会声明变量类型,可以帮助计算机在执行代码前来发现更多潜在的错误,但这样会需要使用者进行更多的思考和编码。反之动态语言则不需要,它很灵活

b. 静态语言在编译后,执行速度一般是大于动态语言的

c. 静态语言结构比较规范,能很方便调试,但需要与大量类型相关的代码。而动态语言不需要与大量类型相关的代码,但如果编写不规范,不容易调试

二、Python的动态添加

2.1 动态添加属性

首先,我们定义一个简单的Person类,它所有姓名和年龄两个属性。并声明一个它的实例对象p。给p动态添加一个属性sex。代码如下所示:

class Person(object):

def __init__(self, name, age):

self.name = name #姓名

self.age = age #年龄

p = Person('Demon', 18)

print(p.name) #Demon

print(p.age) #18

p.sex = 'M' #对对象p动态添加属性sex,并赋值为M

print(p.sex) #M

p2 = Person('Semon', 18) #声明另一个对象p2

# print(p2.sex) #报错:AttributeError: 'Person' object has no attribute 'sex'

从上面的代码可以看出,我们可以直接通过 “对象.新变量名 = 新变量值” 的形式来给对象动态添加一个属性(通过dir(对象名)可以查看当前拥有的属性)。同时当我们重新创建一个新的对象p2,想要调用刚刚动态添加的属性sex时,发现报错了。这说明我们动态创建的属性是只针对当前对象而言的,并不会影响其他对象的使用。这也称之为给对象动态添加属性。

那么,如果我们想要动态添加一个属性,这个属性对所有对象都能生效应该怎么做呢?即我们需要给类动态添加属性,代码如下所示:

class Person(object):

def __init__(self, name, age):

self.name = name #姓名

self.age = age #年龄

p = Person('Demon', 18) #声明一个对象p

p2 = Person('Semon', 18) #声明另一个对象p2

Person.addr = 'SS' #给类动态添加属性

print(p.addr) # SS

print(p2.addr) # SS

2.2 __slots__的使用

简单来说,__slots__的作用就是规定该类能使用的属性是哪些。

import types

class Person(object):

def __init__(self, name, age):

# self.name = name #姓名,在init中定义了name,会报错:AttributeError: 'Person' object has no attribute 'name'

self.age = age #年龄

__slots__ = ('age', 'sex') #而在__slots__中没有定义name,则在init中去使用name会报错

p = Person('Demon', 18) #声明一个对象p

# print(p.name) # AttributeError: 'Person' object has no attribute 'name'

def eat(self):

print('----%s is eating' % self.name)

# p.eat = types.MethodType(eat, p) #AttributeError: 'Person' object has no attribute 'eat'

官方文档中规定__slots__可接受一个字符串、可迭代的类型比如列表,元组等。而且父类中定义的__slots__,在子类中是不生效的。而解决办法就是在子类中自己定义自己的__slots__,并包含父类的定义即可。示例代码如下:

import types

class Person(object):

__slots__ = 'name'

class Student(Person):

#__slots__ = ['name', 'age']

#解决办法是子类自己定义

pass

p = Person()

p.name = 'Demon'

#p.age = 18 #AttributeError: 'Person' object has no attribute 'age'

s = Student()

s.name = 'Demon'

s.age = 18 #子类可以添加

2.3. 动态添加方法

首先,我们从上面已知的属性动态添加的方法进行分析,其实在python中,类并没有方法的概念,它有的都是属性,当我们调用比如p.eat(),其实是先通过p.eat找到一个调用,然后通过(),来执行调用。为了方便我们一般称p.eat()这种形式的称为调用方法(具体后面会再写笔记进行介绍)。既然是这样,我们会想当然的认为可以通过上面介绍的动态添加属性的方式来添加方法,我这样想,也就这样做了,代码如下所示:

class Person(object):

def __init__(self, name, age):

self.name = name #姓名

self.age = age #年龄

p = Person('Demon', 18) #声明一个对象p

p2 = Person('Semon', 18) #声明另一个对象p2

Person.addr = 'SS' #给类动态添加属性

print(p.addr) # SS

print(p2.addr) # SS

def eat1():

print("----eat no self method-----")

def eat2(self):

print("----eat has self method---- %s" % self.name)

p.eat = eat1 #给对象动态指定一个方法

p.eat() # ----eat no self method-----

# p2.eat() # AttributeError: 'Person' object has no attribute 'eat'

p.eat = eat2

# p.eat() #TypeError: eat2() missing 1 required positional argument: 'self'

Person.eat = eat1

Person.eat() #----eat no self method-----

# p2.eat() # TypeError: eat1() takes 0 positional arguments but 1 was given

Person.eat = eat2 #给类动态指定一个方法

p2.eat() #----eat has self method---- Semon

可以看到,通过对象.的方法动态添加方法,应该说只能实现部分的效果,就上述代码的运行情况,我们可以总结如下:

a. 如果添加一个不带self参数的方法,可以直接通过 实例.方法名 的方式添加,也可以通过 类名.方法名添加

b. 如果添加一个带self参数的方法,则只能通过类名.方法名来添加

而从另一个角度,我们都知道,在Python中,类的方法可以分为以下三种:

实例方法(instance method):被类实例调用,第一个参数默认是self

静态方法(static method):可以被类和实例调用,没有默认参数

类方法(class method):可以被类和实例调用,第一个参数默认是类,一般用cls变量名

从之前的测试结果,不带参数的方法,可以通过.的方式来添加,类比如静态方法,我们可以猜测静态方法的动态添加也是通过 . 的方式,测试代码如下:

import types

class Person(object):

pass

@staticmethod

def test_static():

print('aa')

Person.xxxx = test_static # 测试返回值,不一定要命名为固定的名称,可以是任意的

Person.xxxx() # .后的名称与上面一致即可

同样,从我们预测的代码结论里,用类名.可以添加带self参数的方法,而类方法是默认带类对象的方法,我们也尝试用.的方式来添加,测试代码如下:

import types

class Person(object):

num = 0

pass

@classmethod

def test_class(cls):

print(cls.num) #0

Person.xxxx = test_class # 测试返回值,不一定要命名为固定的名称,可以是任意的

Person.xxxx() # .后的名称与上面一致即可

综上两个测试代码可以得出,静态方法和类方法的动态添加和属性的动态添加是一样的实现方式。

而显然唯一不能通过.的方式进行动态添加的就是针对某个对象的实例方法。原因也很简单,实例方法必须第一个参数是实例对象,而方法是在类之后定义了,通过实例对象. 的方式去添加的时候,第一个参数找不着,所以会报错。解决方法是使用types模块中的MethodType(function, instance)。我们可以在IPython3中使用help来查看MethodType的使用文档:

import types

help(types.MethodType)

'''

class method(object)

| method(function, instance)

|

| Create a bound instance method object.

|

| Methods defined here:

|

| __call__(self, /, *args, **kwargs)

| Call self as a function.

|

| __delattr__(self, name, /)

| Implement delattr(self, name).

'''

可以看出,MethodType接受两个参数,第一个参数是需要绑定的函数名,第一个是实例对象。示例代码如下:

import types

class Person(object):

def __init__(self, name, age):

self.name = name #姓名

self.age = age #年龄

p = Person('Demon', 18) #声明一个对象p

def eat(self):

print('----%s is eating' % self.name)

p.eat = types.MethodType(eat, p)

p.eat()

这样我们就完成了实例方法的动态添加。注意使用MethodType需要定义返回,返回的是什么,就用什么来调用。

三、总结

最后总结结论如下:

1. 动态添加实例属性:使用 对象名.新变量名 的方式

2. 动态添加类属性:使用 类.新变量名 的方式

3. 限制类的属性:__slots__

4. 静态方法与类方法:使用 类.新方法 的方式

5. 实例方法:

如果只对某个对象生效:使用types模块中的对象名.新方法名 = MethodType(function, 对象名) 的方式

如果对所有对象生效:使用 类.方法名 的方式

微信搜索【帕森与加瓦】可关注公众号

python动态与静态语言_Python编程笔记--动态属性相关推荐

  1. python动态与静态语言_静态语言和动态语言的区别

    via https://blog.csdn.net/hard_days/article/details/84967298 今天在群里聊天的时候,谈论到python和Java相比居然不用定义变量类型.我 ...

  2. python update skeleton 不自动_python编程笔记(1)-数据类型

    断断续续学了一些,但是后边一直没有使用,就又忘记了.为了缩短学习周期,这次学习的方法:先学主要框架(数据类型.条件.循环.函数.类.numpy.pandas.sklearn),后期直接看朋友code ...

  3. 为什么神经网络用python而不用c语言_python是用C实现的,Java是用C++实现的,那为什么不直接用C或C++呢?...

    人工智能的底层算法通常还是C/C++,其他语言封装了其接口方便调用,所以看起来好像是其他语言,我自己学习时就是使用的C/C++.为什么现在大部分研发人员都使用Python做人工智能方面的实验,一个很重 ...

  4. c语言 动态数组_C语言的学习笔记!助你一路成长!

    1.C语言中函数参数传递是按照"值传递"进行的,即单向传递. 2.函数原型:函数类型 函数名(参数类型,参数类型--),可以不必加参数名,因为操作系统不检查参数名. 3.数组作为实 ...

  5. python画正方形的代码_Python编程练习:使用 turtle 库完成正方形的绘制

    Vuforia点击屏幕自动对焦,过滤UGUI的按钮 //点击屏幕自对对焦 #if UNITY_EDITOR )) #elif UNITY_ANDROID || UNITY_IPHONE &&a ...

  6. python动态运行py代码_Python 动态执行

    Python 动态执行 2015-06-16 Tuesday 在 Python 中,允许通过 exec 和 eval 执行以字符串形式表示的代码片段,这体现了动态语言的特性,可以让代码变得更灵活.实际 ...

  7. python好学么零基础_python编程好学吗 自学行吗

    很多人都说python简单好学,对于有编程经验和一定基础的人来说,学python并不难.但如果是零基础人员,学起来还是有一定难度的.Python相对于其他编程语言来说比较容易,入门简单,对零基础人员比 ...

  8. python怎么调用c语言_Python调用C语言程序方法解析

    Python调用C语言程序方法解析 首先我们需要将编写好的c程序文件编译为动态库文件(后缀名为.so) 使用下面的命令: gcc 原文件名.c -shared -o 新文件名.so 然后在python ...

  9. 可用作python变量名的是_Python编程4:什么是变量

    #少儿编程# 我们在上一篇<Python编程3:与计算机对话之键盘输入input()>中介绍input()函数时曾经使用过变量,将键盘输入的内容赋给变量name.变量,在各个编程语言中都是 ...

最新文章

  1. 噪声对于训练神经网络的重要性
  2. 【运筹学】指派问题、匈牙利法总结 ( 指派问题 | 克尼格定理 | 匈牙利法 | 行列出现 0 元素 | 试指派 | 打 √ | 直线覆盖 ) ★★★
  3. [YTU]_2617(B C++时间类的运算符重载)
  4. MySQL-02:“数据库”操作基本命令及权限笔记
  5. f12 卡 谷歌浏览器_抢券第二课:利用浏览器F12获取优惠券请求链接
  6. Oracle存储过程异常
  7. C语言冒泡排序和选择排序
  8. Java中如何保证线程安全
  9. AES加解密流程及方法
  10. 大数据-zookeeper(上)
  11. java环境变量配置_Java环境变量配置终极版
  12. (word、ppt、excel)​office怎么删除历史文档记录
  13. Urchin.exe使用说明
  14. 微信小程序开发的适合领域
  15. TCP 的三次握手(简述)
  16. R语言字符串字符的大小写转换
  17. 两种参考模型:OSI参考模型、TCP/IP模型
  18. stm32f103c8t6用什么语言编程,STM32F103ZET6和STM32F103C8T6编程不一样吗
  19. VSCode 前端必备插件
  20. KEGGDrug数据库字段认识

热门文章

  1. vb ADO控件连接ACCESS数据库做登录密码的例子
  2. 谐振电路及品质因数(二)
  3. 航空专场 | 无人机设计仿真流程讲解与案例实操
  4. Topy Desk Privacy Policy
  5. Hadoop2.7.2 HBase2.0.0环境搭建
  6. Hive  if null 的用法
  7. kubect安装 windows_k8s安装kubectl top命令
  8. 对残差网络resnet shortcut的解释
  9. 20岁以后增高方法大全
  10. 【CCS仿真系列教程】手把手教你纯软件仿真实现音频滤波