python基础

一. 语法知识

  1. for循环: Python的for循环是作用在任何可迭代对象上,而不是类似于其它语言是建立在下标的基础上。Python中的dict是无下标的,但是它是可迭代对象,所以可以用for循环进行遍历。字符串也是可迭代对象。Python内置的enumerate函数可以把一个list变成索引—元素对,这样就可以在for循环迭代中同时迭代索引和元素本身。
  2. 深浅拷贝shallow and deep copy operations: 这一块主要涉及可变数据类型和不可变数据类型的修改:对于不可变类型进行修改会重新开辟一块内存地址,对于可变类型进行修改则不会重新开辟一块内存地址。python当中的等号赋值是浅拷贝,是将引用传递给一个新的对象。使用内置的deepcopy函数可以实现深拷贝,直接使用copy函数是浅拷贝。在pandas中,重写了copy函数,deep参数为True,可以实现深拷贝。如:a=2 b=a a=4(此时a=4,b=2)这是不可变类型的修改会重新开辟内存,以下代码详细展示了这个过程:
a=4
b=a
print(id(b),id(a))
1743479040 1743479040
a=2
print(id(b),id(a))
1743479040 1743478976

a=[1,2,3] b=a a[2]=4(此时a=b=[1,2,4])。b=a这种是变量赋值,作用和b=a.copy()这种一样,也是属于浅拷贝。浅拷贝对于不可变数据类型是重新开辟内存,对于可变数据类型是共享(通过引用指向)。深拷贝是所有内容完全复制一份。用法如:

import copy
d=copy.deepcopy(a)
  1. 集合set数据类型:set(集合)中的元素无序不能重复。add()增加一个元素,update()参数是一个序列,序列中的每一个元素添加进set集合中
    set数据类型讲解
  2. 模块概念:在python中,一个.py文件就称为一个模块。模块一共有三种:python标准库、第三方模块、应用程序自定义模块。可以通过import test和from test import add两种方式导入一个模块,区别是前一种会将test变量名加载进入名字空间,而后一种只是将add这个变量名加载进来。为了避免模块名冲突,python引入了按目录来组织模块的方法,称为Package。每一个包目录下面都有一个_init_.py的文件,这个文件是必须存在的,否则python就将这个目录当成一个普通目录,而不是一个Package。
    如何把包中模块的路径添入Python中搜索路径sys.path:_file__是一个内置变量,本身是当前脚本文件的相对路径,但是Pycharm会将__file__加成绝对路径。为保证可移植和一般化,需要进一步处理(自己处理成相对路径)。os模块中有一个方法os.path.abspath(file)把相对路径变成绝对路径。加上这几行代码之后把当前项目的顶层目录加入python解释器的搜索路径,可以保证所有包中(同一个包内或不同包内)的模块可以相互调用。 name 属性也是一个内置变量,它被默认设置为当前模块的模块名,但当前模块作为执行脚本时 name =” main _”(主要是测试的时候用),所以一般的逻辑代码是放在这么一种结构中:
    if _ name =” main _”
import os,sys
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

二.常用函数

  1. 匿名函数(lambda表达式): 关键字lambda表示匿名函数,冒号前面的表示函数参数。匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。匿名函数不用担心命名冲突,匿名函数也是一个函数对象,也可以把一个匿名函数赋值给一个变量,再利用变量来调用该函数。lambda主体是将结果写成一个顺畅的表达式,因为仅限于表达式,所以lambda的功能要比函数简单得多,lambda是为一个简单函数而设计的,而def是处理更大的任务
    f=lambda x, y, z : x + y + z
    f(2, 3, 4)
  2. map函数和reduce函数:
    这两个函数如果运用得好,确实会大大简化程序的编写。map函数的两个参数分别是一个定义的函数引用,一个可迭代对象,其作用就是定义好的函数作用于可迭代对象中的每一个元素,返回值是一个迭代器,迭代器是惰性计算序列,进一步操作不可以直接输出,还得进一步转化(这也就是为什么还得用list()才会有值输出的原因)。reduce函数把一个函数作用在一个序列上,这个函数必须接受两个参数,reduce把结果继续和序列的下一个元素做累积运算。使用reduce函数必须添加相应的模块。
  3. filter函数:
    filter()的作用是从一个序列中筛选出符合条件的元素。由于filter使用了惰性计算,所以只有在取filter()结果的时候,才会真正筛选并每次返回下一个筛选出的元素。Filter函数有两个参数,一个时作用的函数,另一个是施加作用的序列(列表)
  4. 内置的基础函数:
    id()可以查看一个对象的内存地址;5/2=2.5,5//2=2;type()和isInstance()都可以验证一个数据是否是某种数据类型

三.正则表达式

  1. 写正则表达式时,为什么要加上re.S
    Make the ‘.’ special character match any character at all, including a newline; without this flag, ‘.’ will match anything except a newline.
  2. 正则匹配中search,match,findall的差别
    match()函数只检测RE是不是在string的开始位置匹配,search()会扫描整个string查找匹配,也就是说match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none。search()会扫描整个字符串并返回第一个成功的匹配。
    下面这段话时官方文档中对findall的解释:

Return all non-overlapping matches of pattern in string, as a list of strings. The string is scanned left-to-right, and matches are returned in the order found. If one or more groups are present in the pattern, return a list of groups; this will be a list of tuples if the pattern has more than one group. Empty matches are included in the result unless they touch the beginning of another match.

  1. 正则表达式中关于\的使用
    在正则中,反斜杠为元字符时,要用\表示,在Python中反斜需要转义,每个\要又要写成\,所有就成了\\。Python中字符串前面加上 r 表示原生字符串,此时如果想表示\,可以直接写成r‘\’。’\d’可以直接表示成r’\d’

四.参数特性

一般来说,传送过去的函数参数是共享对象的引用值,引用是用指针的形式实现的。所以所有的参数实际上都是通过指针进行传递的,被传递的对象从来不自动拷贝。

def changer(a, b):
    a=2
    b[0]='spam'
X=1
L=[1, 2]
changer(X, L)
X, L
####输出是(1,['spam',  2])
L=[1, 2]
changer(X, L[:])    
X, L
####输出是(1,[1, 2])

Python中函数参数出现的顺序遵循以下有关顺序的法则:
任何位置参数(value), 后面跟着任何关键字参数(name=value)和*sequence形式的组合,后面跟着
**dict形式的参数。(如果不是按这个顺序来,在python2中会报错,python3中报错或者时编程Keyword-only参数)。python内部是使用以下的步骤来在赋值前进行参数匹配的:

  • 通过位置分配非关键字参数;
  • 通过匹配变量名分配关键字参数;
  • 其它额外的非关键字参数分配到*name元组中;
  • 其它额外的关键字参数分配到**name字典中去;
  • 用默认值分配给在头部未得到分配的参数
def f(a, b, c):
    print(a, b, c)
f(1, c=3, b=2)          ##在一个调用中混合使用基于位置的参数和基于关键字的参数都可以

def func(spam, eggs, toast=0, ham=0):
    print((spam,eggs, toast, ham))
func(1,ham=1, eggs=0)    
###关键字参数在调用过程中使用时,参数排列的位
###置并没有关系,python通过变量名进行匹配,而不是位置           
###输出是(1,0,0,1)

关键字参数是在函数调用时出现,如def f(a, b, c): …;在调用时f(c=2, 1, a=3)这种调用也是可以的。
默认参数是在函数定义时出现,如def f(a, b=2, c=3):…; 在调用时b, c既可以按位置给出,也可以按关键字给出,也可以不给出。
任意参数(针对函数定义):

def f(a, *pargs, **kargs):
    print(a, pargs, kargs)
f(1, 2, 3, x=1, y=2)
###输出是: 1 (2,3) {'y':2, 'x':1}

解包参数(针对函数调用,用元组和字典对位置参数进行赋值)

def func(a, b, c, d):
    print(b)
    print(a, b, c, d)
func(1, *(2,3), **{'d':4})
###输出是:1,2,3,4

别混淆函数定义或函数调用时*/**的语法:在定义时,它意味着收集任意数量的参数,而在调用时,它解包任意数量的参数。
Keyword-only参数(python3才有)

def kwonly(a, *b, c):          ###a可以按照关键字或位置传递,b收集任何额外的位置参数,c必须按照关键字传递
    print(a,b,c)               ###定义时也可以是def kwonly(a, *b, c=7), c也必须按照关键字传递
kwonly(1,2,3)           ###TypeError,报错

def kwonly(a, *, b='spam', c='ham'):
    print(a, b, c)
###此时*在定义中不代表接受任意参数的意思,只表示b,c必须是按关键字传递

LEGB原则
作用域分为四层,最外层库即build_in,次一层全局变量,次一层嵌套作用,最里面一层局部作用域变量的查找顺序时LEGB(E:Enclosing function local)。在函数外定义的变量(count=10)就是全局变量,全局变量在函数定义里不能被修改,如果一定要修改,使用global count。两个函数嵌套时,如果想在里层的函数定义里修改外层的函数定义里局部变量,必须加一个nonlocal count。默认参数(parament=’female’函数定义中有这种形式的)一定要用不可变对象,如果用可变对象,无参数调用时使用了默认参数,函数中默认参数变量是会记住这一次默认参数变量里的内容,下一次调用就会产生逻辑错误。

五.字典

列表是有序集合,字典是无序集合。它们之间的主要差别是:字典当中的元素是通过键来存取的,而不是通过偏移存取。从本质上讲,字典是作为散列表(支持快速检索的数据结构)来实现的,一开始很小,并根据要求增长。此外,python采用最优化的散列算法来寻找键,因此搜索是很快速的。和列表一样,字典存储的是对象引用(不是拷贝)。
与列表不同的是,每当对新字典键进行赋值(之前没有被赋值的键),就会在字典内生成一个新的元素。在列表中,python会将超出列表末尾的偏移视为越界并报错。要想扩充列表,需要使用append方法或分片赋值(lists[3:5]=[6,7])来实现。键存在测试方法has_key在python3.0中已经取消了,由in表达式代替。

'__class__',
'__contains__',
'__delattr__',
'__delitem__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__setitem__',
'__sizeof__',
'__str__',
'__subclasshook__',
'clear',
'copy',
'fromkeys',
'get',
'items',
'keys',
'pop',
'popitem',
'setdefault',
'update',
'values'

使用for-loop遍历字典:

for x in dic:      #和写成for x in D.keys():的效果是一样的
    print(x,dic[x])

键不一定总是字符串:任何不可变对象(列表可变)都是可以的,例如常量,数字,元组(Matrix={(2,3,4):88,(7,8,9):99},25:66)。
使用zip函数的字典和列表创建方法:

list(zip(['a','b','c'],[1,2,3]))
# [('a', 1), ('b', 2), ('c', 3)]
D=dict(zip(['a','b','c'],[1,2,3]))
# {'a': 1, 'b': 2, 'c': 3}
D={k:v for (k,v) in zip(['a','b','c'],[1,2,3])}   #使用解析方式创建的字典,python3.0才可以

视图:在python3.0中,字典的keys、values和items都返回视图对象,而在python2.6中,它们返回实际的结果列表。视图是可迭代的,这就意味着对象每次产生一个结果项,而不是在内存中立即产生结果列表。可迭代对象如果想用列表操作或显示它们的值,需要通过list函数。
如何对字典进行有序操作

D={'a':1,'b':2,'c':3}
Ks=D.keys()    
Ks=list(Ks)             ###使用keys函数返回的对象是一个迭代器,使用list才能遍历迭代器中的值
Ks.sort()
for k in Ks: 
    print(k,D[k])

enumerate函数的解释:enumerate(iterable,start=0)

seasons = ['Spring', 'Summer', 'Fall', 'Winter']
print(list(enumerate(seasons)))
print(list(enumerate(seasons, start=1)))
#结果
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

enumerate函数的源码:

def enumerate(sequence, start=0):
    n = start
    for elem in sequence:
        yield n, elem
        n += 1
OrderedDict

Return an instance of a dict subclass, supporting the usual dict methods. An OrderedDict is a dict that remembers the order that keys were first inserted. If a new entry overwrites an existing entry, the original insertion position is left unchanged. Deleting an entry and reinserting it will move it to the end.

>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}

>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])

六. 列表list

列表中可以包含任何种类的对象:数字、字符串甚至其它列表。列表是可变对象,它们都支持在原处修改的操作,可以通过指定的偏移值和分片、列表方法调用、删除语句等方法来实现。列表是任意对象的有序集合。列表支持很多与字符串相同的操作,如列表对“+”和“*”操作与字符串相似,两个操作的意思也是合并和重复,结果是一个新的列表。
列表带有的操作可以直接修改列表对象,而不会像字符串那样强迫你建立一个新的拷贝。列表中索引和分片的赋值都是原地修改,它们对列表进行直接修改,而不是生成一个新的列表作为结果。已知一个列表L的值为[1,2,3],赋值操作L[1:2]=[4,5]会把L修改成列表[1,4,5,2,3]。python会先删除2,然后再删除2的地方插入4和5。

['__add__',
'__class__',
'__contains__',
'__delattr__',
'__delitem__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__gt__',
'__hash__',
'__iadd__',
'__imul__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__mul__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__reversed__',
'__rmul__',
'__setattr__',
'__setitem__',
'__sizeof__',
'__str__',
'__subclasshook__',
'append',
'clear',
'copy',
'count',
'extend',
'index',
'insert',
'pop',
'remove',
'reverse',
'sort']

比较典型的列表解析式:

[xv if c else yv
for c, xv, yv in zip(condition, x, y)]
##################################################
return [tuple(s[i] for s in seqs) for i in range(minlen)]

七.生成器generator

有两种语言结构可以延迟结果创建:生成器函数,编写为常规的def语句,但是使用yield语句一次返回一个结果,在每个结果之间挂起和继续它们的状态;生成器表达式,类似于列表解析,但是,它们返回按需产生结果的一个对象,而不是构建一个结果列表。
简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。另一个 yield 的例子来源于文件读取。如果直接对文件对象调用 read() 方法,会导致不可预测的内存占用。好的方法是利用固定长度的缓冲区来不断读取文件内容。通过 yield,我们不再需要编写读文件的迭代类,就可以轻松实现文件读取。
生成器函数和常规函数之间的主要不同之处在于,yields一个值,而不是返回一个值。yields语句挂起该函数并向调用者发送回一个值,但是保留足够的状态以使得函数能够从它离开的地方继续。

def squares(n):
    for i in range(n):
        yield i**2
    return None
g=squares(10)
print(g)                           ###<generator object squares at 0x000002742152F150>
#######python2.6及以前版本,为next(),2.6之后的版本是__next__(),也可以写成next(g)
g.__next__()                    ### 0
g.__next__()                    ###1
g.__next__()                    ###4

生成器表达式不是在内存中构建结果,而是返回一个生成器对象,这个对象将会支持迭代协议并在任意的迭代语境中操作

[x**2 for x in range(4)]
Out[18]: [0, 1, 4, 9]

(x**2 for x in range(4))
Out[19]: <generator object <genexpr> at 0x00000274214685C8>

G=(x**2 for x in range(4))

list(G)
Out[21]: [0, 1, 4, 9]

生成器是单迭代器对象,如果你手动地使用多个迭代器来迭代结果流,它们将指向相同的位置。

G=(c*4 for c in "SPAM")

I1=iter(G)

I2=iter(G)

next(I1)
Out[26]: 'SSSS'

next(I2)
Out[27]: 'PPPP'

编写自己的map(func, …),这里还有函数定义当中的接收不定长参数:

###生成器方式
def mymap(func,*seqs):
    res=[]
    for args in zip(*seqs):
        yield func(*args)

print(list(mymap(abs,[-1,-2,0,3,-5])))
[1, 2, 0, 3, 5]
print(list(mymap(pow,[1,2,3],[3,2,1])))
[1, 4, 3]

###生成器表达式
def mymap(func,*seqs):
    return (func(*args) for args in zip(*seqs))

print(list(mymap(abs,[-1,-2,0,3,-5])))
[1, 2, 0, 3, 5]
print(list(mymap(pow,[1,2,3],[3,2,1])))
[1, 4, 3]

###zip()的源码
ef myzip(*seqs):
    seqs=[list(s) for s in seqs]
    print(seqs)
    print(all(seqs))
    res=[]
    while all(seqs):
        res.append(tuple(s.pop(0) for s in seqs))
    return res

print(myzip('abc','xyz123'))
[['a', 'b', 'c'], ['x', 'y', 'z', '1', '2', '3']]
True
[('a', 'x'), ('b', 'y'), ('c', 'z')]

八. argparse包的使用

一篇非常好的argparse的turtorial

The argparse module makes it easy to write user-friendly command-line interfaces. The program defines what arguments it requires, and argparse will figure out how to parse those out of sys.argv.
The argparse module also automatically generates help and usage messages and issues errors when users give the program invalid arguments.

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,help="display a square of a given number")                         ###positional argument
parser.add_argument("-v", "--verbose", action="store_true",help="increase output verbosity")              ###optional argument
args = parser.parse_args()
answer = args.square**2
if args.verbose:
    print("the square of {} equals {}".format(args.square, answer))
else:
    print(answer)

####把上面的.py文件保存为prog.py,在命令行下调用
$ python3 prog.py
usage: prog.py [-h] [-v] square
prog.py: error: the following arguments are required: square
$ python3 prog.py 4
16
$ python3 prog.py 4 --verbose
the square of 4 equals 16
###     Note that the order does not matter.
$ python3 prog.py --verbose 4
the square of 4 equals 16

optional arguments包含多个可选值:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
    print("the square of {} equals {}".format(args.square, answer))
elif args.verbosity == 1:
    print("{}^2 == {}".format(args.square, answer))
else:
    print(answer)
 ### 在命令行下运行
$ python3 prog.py 4 -v 3
usage: prog.py [-h] [-v {0,1,2}] square
prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)
$ python3 prog.py 4 -h
usage: prog.py [-h] [-v {0,1,2}] square

positional arguments: square display a square of a given number

optional arguments: -h, --help show this help message and exit -v {0,1,2}, 
--verbosity {0,1,2} increase output verbosity 

action="count"关键字和default关键字:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,help="display a square of a given number")
parser.add_argument("-v", "--verbosity", action="count", default=0,help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity >= 2:
    print("the square of {} equals {}".format(args.square, answer))
elif args.verbosity >= 1:
    print("{}^2 == {}".format(args.square, answer))
else:
    print(answer)
###在命令行下运行
$ python3 prog.py 4
16

We’ve just introduced yet another keyword, default. We’ve set it to 0 in order to make it comparable to the other int values. Remember that by default, if an optional argument isn’t specified, it gets the Nonevalue, and that cannot be compared to an int value (hence the TypeError exception).

import argparse

parser = argparse.ArgumentParser(description="calculate X to the power of Y")
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
args = parser.parse_args()

answer = args.x**args.y

if args.quiet:
    print(answer)
elif args.verbose:
    print("{} to the power {} equals {}".format(args.x, args.y, answer))
else:
    print("{}^{} == {}".format(args.x, args.y, answer))

###在命令行下运行
$ python3 prog.py 4 2
4^2 == 16
$ python3 prog.py 4 2 -q
16
$ python3 prog.py 4 2 -v
4 to the power 2 equals 16
$ python3 prog.py 4 2 -vq
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
$ python3 prog.py 4 2 -v --quiet
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose

九.静态方法和类方法

python通过静态方法的概念,嵌套在一个类中的没有self参数的简单函数,并且旨在操作类属性而不是实例属性。静态方法不会自动接受一个的self参数,不管是通过一个类还是通过一个实例调用。它们通常会记录跨越所有实例的信息,而不是为实例提供行为。Python3.0通过类调用无self函数,这个函数就具有了静态方法的属性。

class Spam:
    numInstance=0        ####        类属性是所有实例共享的
    def __init__(self):
        Spam.numInstance=Spam.numInstance+1
    def printNumInstance():
        print("Number of Instances created:",Spam.numInstance)
        
a=Spam()
b=Spam()
c=Spam()

Spam.printNumInstance(####Number of Instances created: 3
c.printNumInstance()                       
####TypeError: printNumInstance() takes 0 positional arguments but 
####1 was given    这个地方说明通过实例调用实例方法时,会将实例名通
####过self参数传递给具体调用到的方法

静态方法替代方案:

class Spam:
    numInstance=0
    def __init__(self):
        Spam.numInstance=Spam.numInstance+1
        
def printNumInstance():                                                            
### 为什么在类之外的函数可以使用类属性,因为类名称对简单函数而言是可
###读取的全局变量
        print("Number of Instances created:",Spam.numInstance)    
        
a=Spam()
b=Spam()
c=Spam()

printNumInstance()

真正的静态方法和动态方法(调用内置函数staticmethod和classmethod):

class Method:
    def __init__(self):
        Method.smeth=staticmethod(Method.smeth)
        Method.cmeth=classmethod(Method.cmeth)
    
    def imeth(self,x):
        print(self,x)
    
    def smeth(x):
        print(x)
        
    def cmeth(cls,x):
        print(x)
obj=Method()
obj.imeth(1)                              ###常规的实例方法

Method.imeth(obj,2)                ###通过类来调用常规的实例方法

Method.smeth(3)                     
###类调用静态方法,在python3.0中
###不使用staticmethod函数,只要不写self参数也具有静态函数属性
obj.smeth(4)                             

Method.cmeth(5)                     
###使用classmethod变成类方法后,
###类调用时才会默认传递一个不可见的类名参数
obj.cmeth(6) 

在python3中有了装饰器以后,也可以直接使用装饰器的方法来调用:

  • @classmethod means:
    when this method is called, we pass the class as the first argument instead of the instance of that class (as we normally do with methods). This means you can use the class and its properties inside that method rather than a particular instance.
  • @staticmethod means:
    when this method is called, we don’t pass an instance of the class to it (as we normally do with methods). This means you can put a function inside a class but you can’t access the instance of that class (this is useful when your method does not use the instance).
注意点

类的静态方法是指在类的定义之外,可以不通过实例来调用。并不是说在类中可以被其它正常的类方法调用。类的定义中一个类方法调用另一个类方法还是得通过self参数来指定调用的实例。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值