Python笔记_第四篇_高阶编程_实例化方法、静态方法、类方法和属性方法概念的解析。
1.先叙述静态方法:
我们知道Python调用类的方法的时候都要进行一个实例化的处理。在面向对象中,一把存在静态类,静态方法,动态类、动态方法等乱七八糟的这么一些叫法。其实这些东西看起来抽象,但是很好理解。这里面有一个难点就是静态方法的理解,我们先叙述这个概念。
比如在C#语言中,我们一般在在一个类前面加上类似于staci这样的关键字
public 类名{
static void 方法(){
}
}
一般这个时候方法可以直接用“类名.方法名”的方式直接调用类中的方法。其实这种方法叫做直接引用的方法,不需要通过其他的"new"一个实例化去引用。
为什么会存在这么两种方法去取调用类中的方法属性呢?其中有这么一些原因和误解:
* "静态方法常驻内存,实例化方法不是,所以静态方法效率高但占内存"?
事实上,他们都是一样的,在加载时机和占用内存上,静态方法和实例化方法是一样的,在类型第一次被使用时加载。调用的速度基本上没有差别。
* "静态方法在对上分配内存,实例化方法在堆栈上"?
事实上所有的方法都不可能在堆或者栈上分配内存,方法作为代码是被加载到特殊的代码内存区域,这个内存区域是不可写的。
方法占不占更多的内存和他是不是“静态”没有什么关系。
因为字段使用阿里存储每个实例对象的信息的,所以字段会占有内存,并且因为每个实例对象的状态都不一致(至少补鞥呢认为它们是一致的),所以每个实例对象的所有字段都会在内存中有一份拷贝,也因为这样拟采用它们来区分现在操作的那个对象。但是方法不一样,不论有多少实例对象,它们的方法和代码都是一样的,所以只要有一份代码就高了。因此无论是静态还是非静态的方法都只存在一份代码,也就是只占用一份内存空间。
同样的代码,为什么运行起来表现不一样?这就依赖于方法所用的数据了,只要有两种数据来源,一种是通过方法的参数传进来,另一种就是使用class成员变量的值。(这句话非常重要,后面代码会说明这个)
* “实例方法需要先创建实例才可以调用,比较麻烦静态方法不用,比较简单”?
事实上如果一个方法与他所在类的实例对象无关,那么他就应该是静态的,而不应该把它写成实例方法。所以所有的实例方法都与实例有关,既然与实例有关,那么创建实例就是必然的步骤,没有麻烦简单一说。当然你可以完全把所有的实例方法都写成静态的,将实例作为参数传入即可,一般情况下不会出什么问题。从面向对象的角度来说,在抉择使用实例化方法还是静态方法时,应该根据是否该方法和实例化对象具有逻辑上的相关性,如果是!就应该使用实例化对象,反之使用静态方法。这是从面向对象角度上来说的。如果从线程安全,性能,兼容性上来看,也是选用实例化方法为宜。
* “为什么我们要把方法区分为:静态方法和实例化方法?”
如果我们要继续深入研究的话,就要脱离技术谈理论了。早期的结构化编程,几乎所有的方法都是“静态方法”,引入实例化方法概念是面向对象概念出现之后的事情了。区分静态方法和实例化方法不能单单从性能上去立即,创建C++、java、C#这样面向对象语言的大师引入实例化方法一定不是为了解决什么性能,内存问题,而是为了让开发更加模式化、面向对象。这样说的话,静态方法和实例化方法的区分是为了解决模式问题。
举例说明:
比如“人”这个类,每个人都有姓名、年龄、性别、身高等,这些属性就应该是非静态的,因为每个人都是的这些属性都不相同;但人在生物学上属于哪个部门哪个纲那么目等,这些属性属于整个人类,这就应该是静态的--他不依赖某个特定的人。
2. 关于装饰器的再理解:
装饰器我们前面用到过可以在不改变函数本身的情况下,可以通过外部的更改对整个函数的内容进行“添加”某些参数,方法等。我们发现像C#这样的语言没有装饰器这么一说,但是像C#这样语言如果想定义一个静态方法前面要添加一个static这样的变量。这样我们就是能再更加深入的理解Python这个装饰器其实就是把一些需要进行“特性变更”的部分,单独拿出来作为一种单独的“功能”,对需要特性变更的部分进行“装饰”、“装修”、“安装”,是对面向对象概念的更进一步的提升(其实学过其他面向对象语言的人觉得Python当中怎么没有静态方法这些东西,其实Python把他们进行再进一步提炼,用一个装饰器来作为一个工具去使用了,有时候觉得怪怪的而已)。
3. 四个概念的排列:
实例化方法:在类中,第一个参数必须是实例对象,该参数名一般约定为“self”,通过他来传递实例的属性和方法。也可以传递类的属性和方法。注意:这里的self可以用其他传参来代替,但是约定为self,且为了区分静态方法,这里的传参必须要写上self。实例化的格式:实例化变量 = 类名()。
调用:只能由实例对象调用。
装饰器:无装饰器!
静态方法:千万不要写“self”和“cls”参数。其他参数随意,用于区分实例化方法和类方法。但是方法中不能使用类或实例的任何属性和方法。
调用:实例对象和类对象都可以调用。为了区分笔建议直接用类调用:类名.实例化方法。
装饰器:@staticmethod
类方法:第一个参数必须是当前类对象,该参数名一般约定为“cls”参数,建议写上“cls”,通过他来传递类的属性和方法(但是不能传递实例的属性和方法)
调用:实例对象和类对象都可以调用。
装饰器:@classmethod
属性方法(静态属性方法):属性方法这里指的是静态属性方法。调用可以直接.点的方式调用,调用不能有()。否则会报错。属性方法是可以把个类当中的属性通过方法的方式进行静态的调用。
调用:如果只对本类的属性进行静态处理不需要用实例化方法,如果通过方法去更改属性值且再调用这个方法需要实例化方法。
装饰器:@property 和 @属性/方法.setter
4. 分别举例说明:
4.1 实例化方法(略)
4.2 静态方法:
import time class TimeTest(object):
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
self.second = second @staticmethod
def showTime():
return time.strftime("%H:%M:%S", time.localtime()) print(TimeTest.showTime())
t = TimeTest(, , )
nowTime = t.showTime()
print(nowTime)
备注:注意到staticmethod里面是没有参数的,但是可以有参数,就是不能有self和cls参数,我们看到可以直接静态方法调用,也可以实例化方法调用。
4.3 类方法:
class ClassTest(object):
__num = @classmethod
def addNum(cls):
cls.__num += @classmethod
def getNum(cls):
return cls.__num # 这里我用到魔术方法__new__,主要是为了在创建实例的时候调用累加方法。
def __new__(self):
ClassTest.addNum()
return super(ClassTest, self).__new__(self) class Student(ClassTest):
def __init__(self):
self.name = '' a = Student()
b = Student()
print(ClassTest.getNum())
备注:其实我们这里看到了,类方法修饰类的_属性。注意这里添加的cls。我们用静态类方法可以直接调用。
4.4 属性方法:
class Person(object):
def __init__(self,name):
self.name = name
self.food = None @property
def eat(self):
print("%s 正在吃 %s" %(self.name,self.food)) @eat.setter
def eat(self,food):
self.food = food p1 = Person("Thomas")
p1.eat = "meat"
p1.eat
# Thomas 正在吃 meat
class Person(object):
def __init__(self,age):
# 属性直接对外暴露,改为限制访问的方式
self.__age = age
# 方法名为受限制的变量去掉双下划线的方式访问
@property # 其实也是一种装饰器 这个就是get方法的意思
def age(self):
return self.__age
@age.setter # 去掉下划线.setter 这个就是set方法的意思
def age(self,age):
if age < :
age =
else:
self.__age = age print(Person().age)
#
备注:我们通过第一个例子得到,我们用一个方法调用属性后再通过这个方法赋值,只能用实例的方式,如果我们用这个方法只是去修改属性值。可以直接把属性值点出来。后面那个例子在get和set的方式里面我们提到过。
Python笔记_第四篇_高阶编程_实例化方法、静态方法、类方法和属性方法概念的解析。的更多相关文章
- Python笔记_第四篇_高阶编程_进程、线程、协程_5.GPU加速
Numba:高性能计算的高生产率 在这篇文章中,笔者将向你介绍一个来自Anaconda的Python编译器Numba,它可以在CUDA-capable GPU或多核cpu上编译Python代码.Pyt ...
- Python笔记_第四篇_高阶编程_魔法(术)方法详解(重载的再详解)
1. 魔法方法是什么? 魔法方法(Magic Method)是Python比较独特的应用,它可以给你的类增加特殊的方法,如果你的对象实现了(重载),这些方法中的某一个,就会被Python所调用.正如装 ...
- Python笔记_第四篇_高阶编程_再议装饰器和再议内置函数
1. 概述: 我们在前面用了很多的装饰器这个工具的方法.这个位置要系统的讲一下装饰器. 1.2 为什么需要装饰器. 装饰器本质是一个Python函数,它可以让其他函数在不需要任何代码变动的前提下增加额 ...
- Python开发【第十三篇】高阶函数、递归函数、闭包
函数式编程是指用一系列函数解决问题 好处:用每个函数完成每个细小的功能,一系列函数任意组合能够解决大问题 函数仅仅接收输入并产生输出,不包含任何能影响输出的内部状态 函数之间的可重入性 当一个函数的输 ...
- python学习三十四天函数高阶函数定义及用法
python函数高阶函数是把函数当成一个变量,传递给函数作为参数,或者函数的返回值里面有函数,都称为高阶函数, 1,把函数作为参数传递 def dac(x,y): return x+y def tes ...
- Python笔记_第四篇_高阶编程_正则表达式_2.正则表达式入门
1. 匹配单个字符和数字: . --->> 匹配除换行符以外的任意字符.[0123456789] --->> []字符集合,表示匹配方括号中所包含的任意一个字符.[Thomas ...
- Python笔记_第四篇_高阶编程_进程、线程、协程_4.协程
1.协程的概念: 子程序或者子函数,在所有语言中都是层级调用,比如A调用B,再B执行的过程中又可以调用C,C执行完毕返回,B执行返回,最后是A执行完毕返回.是通过栈来实现的,一个线程就是执行一个自称, ...
- Python笔记_第四篇_高阶编程_进程、线程、协程_3.进程vs线程
1.多任务的实现原理: 通常我们会设计Mater-Workder模式,Master负责分配任务,Worker负责执行任务,因此多任务环境下,通常是一个Master,多个Worker 2.多进程: 主进 ...
- Python笔记_第四篇_高阶编程_进程、线程、协程_1.进程
1. 多任务原理: 现代操作系统,像win,max os x,linux,unix等都支持多任务. * 什么叫做多任务? 操作系统可以同时运行多个任务. * 单核CPU实现多任务原理? 操作系统轮流让 ...
随机推荐
- PHP页面跳转以及伪登录实例
PHP页面跳转一.header()函数header()函数是PHP中进行页面跳转的一种十分简单的方法.header()函数的主要功能是将HTTP协议标头(header)输出到浏览器. header() ...
- Spring Boot2(005):关于代码结构
spring boot 对于工程代码结构并没有特殊得要求,但以下几个有用的最佳实践建议参考参考: 1.不鼓励而且应该避免使用 default 包 没有 package 声明的类被认为是在 defaul ...
- Docker 容器shell
版权所有,未经许可,禁止转载 章节 Docker 介绍 Docker 和虚拟机的区别 Docker 安装 Docker Hub Docker 镜像(image) Docker 容器(container ...
- Python 简单统记Log 日记 下次用:python的内置logging模块 easy
环境 win7 先来new一点log 日记 日记包含 "reason=", "error=" 两个log级别 存放在D盘下得LOG目录下 先来 生 ...
- Glusterfs volume 的三种挂载方式
在上一篇中我们介绍了Glusterfs在CentOS7上的安装,并且提到Glusterfs client端有三种:Native client,NFS,Samba, 今天我们就来一起学习下这三种方式. ...
- OpenCV学习日志:计算机视觉资源汇总
1.1 重要会议 (1)机器视觉重要会议 CVPR:Conferenceon Computer Vision and Pattern Recognition, IEEE, 五星 ICCV:Intern ...
- 洛谷 P2516 [HAOI2010]最长公共子序列
题目传送门 解题思路: 第一问要求最长公共子序列,直接套模板就好了. 第二问要求数量,ans[i][j]表示第一个字符串前i个字符,第二个字符串前j个字符的最长公共子序列的数量 如果f[i][j]是由 ...
- 【LeetCode】跳跃游戏II
[问题]给定一个非负整数数组,你最初位于数组的第一个位置.数组中的每个元素代表你在该位置可以跳跃的最大长度.你的目标是使用最少的跳跃次数到达数组的最后一个位置. 示例: 输入: [,,,,] 输出: ...
- mybatis环境搭建(eclipse,idea)
基于java配置SSM,eclipse 新建maven,web项目 .... 项目结构: jar包 pom.xml spring和DispatcherServlet上下文 public class D ...
- 十六、CI框架之数据库操作get用法
一.使用数据库的Get方法读取内容,如下代码: 二.数据库如下: 二.效果如下: 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:382477247)哦, ...