Python语言特性

1. Python的函数参数传递

​ 看两个如下例子,分析运行结果

#代码1
a = 1
def fun(a):
a = 2
fun(a)
print(a) #1
#代码2
a = []
def fun(a):
a.append(1)
fun(a)
print(a) #[1]

所有的变量都可以理解为内存中的一个对象的引用,或者也可以看似C中void*的感觉。

这里记住的是类型是属于对象的,而不是变量的。而对象有两种,可更改(mutable)与不可更改(immutable)对象。在python中,strtupleint是不可更改的对象,而listdict等则是可以修改的对象。

当一个引用传递给函数的时候,函数自动复制一份引用,这个函数的引用和外边的引用没有半毛钱关系,所以第一个例子里函数把引用指向一个不可更改的对象,当函数返回的时候,外面的引用没感觉,而第二个例子就不一样,函数内部的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改。

2.Python中的元类【metaclass

​ 元类就是创建类的东西。创建类就是为了创建类的实例对象,但是我们已经学习到了python中的类也是对象。元类就是用来创建这些类(对象)的。元类就是类的类。

3.静态方法@staticmethod和类方法@classmethod

Python其实有3个方法,分别是静态方法、类方法、实例方法。

class A(object):
def foo(self,x):
print("saada%s"%(self,x))
@classmethod
def class_foo(cls,x):
print("asdsad%s"%(cls,x))
@staticmethod
def static_foo(x):
print("adad%s"%(x))
a = A()

先理解函数参数里面的self、cls 这个self和cls是类或者实例的绑定,对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是foo(self,x),为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数。调用的时候是这样的a.foo(x)其实foo(a,x)类方法一样,只不过它的传递是类而不是实例A.class_foo(x),注意这里的self和cls可以替换别的参数。

对于静态方法其实和普通方法一样,不需要对谁进行绑定,唯一的区别是调用的时候使用a.statis_foo(x)或者A。static_foo(x)来调用。

\ 实例方法 类方法 静态方法
a = A() a.foo(x) a.class_foo(x) a.static_foo(x)
A 不可用 A.class_foo(x) A.static_foo(x)

4.类变量和实例变量

class Person:
name = 'aaa'
p1 = Person()
p2 = Person()
p1.name = 'bbb'
print(p1.name)#bbb
print(p2.name)#aaa
print(Person_name)#aaa

类变量就是供类使用的变量

实例变量就是供实例使用的变量

这里的p1.name = ‘bbb’是实例调用了类变量,者其实和上面第一个问题一样,就是函数传参的问题,p1.name一开始是指向类变量name=‘aaa’,但是在实例作用域里类变量的引用改变了,就变成了一个实例变量。self.name,不再引用Person的类变量name。

#例子
class Persson:
name = []
p1 = Person()
p2 = Person()
p1.name.append(1)
print(p1.name)#[1]
print(p2.name)#[1]
print(Pseron.name)#[1]

5.Python自省

这属于python彪悍的特性。

自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型,简单一句就是运行的时候能够知道对象的类型,比如:typedirgetattrhasattrisinstance

6.字典推导式

d = {key:value for (key,value) in iterable}

7.Python中单下划线和双下划线

class MyClass():
def __init__(self):
self.__superprivate = 'Hello'
self._semiprivate = 'world' mc = MyClass()
print(mc.__superprivate)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
print(mc._semiprivate)
world
print(mc.__dict__)
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}

__foo__是一种约定,python内部的名字,用来区别其他用户自定义的命名,防止冲突。

_fo是一种约定,用来指定变量私有。

__foo是解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名。

8.字符串格式化%s和format

format在许多方面更便利,对于%s更烦人的是它无法同时传递一个变量和元组。

"hi %s" % name

如果name是(1,2,3),它将会抛出TypeError异常,为了保证它总是正确的,你必须这么做

"hi %s"%(name,)#提供一个单元素的数组而不是一个参数

9.迭代器和生成器

在Python中,一边循环中一边计算的机制,称为生成器generator

可以被next函数调用并不断返回下一个值的对象称为迭代器iterator

10.*args和**args

当不确定函数将要传递多少个参数的时候可以用*args。

def print_1(*args):
for count,thing in enumerate(*args):
print("{0}{1}".format(count,thing))

**args允许你使用没有事先定义的参数名

def print_1(**kwargs):
for name,value in kwargs.items():
print("{0}{1}".format(name,value))

11.面向切面编程AOP和装饰器

装饰器是一种设计模式

经常用于切面需求的应用场景

较为经典的有

  • 插入日志
  • 性能测试
  • 事务处理

装饰器是解决这类问题的绝佳设计。

有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。

装饰器的作用就是为已经存在的对象添加额外的功能。

12 鸭子类型

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。

比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。

又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等.

鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式。

13.重载

函数重载主要是为了解决两个问题

  • 可变参数类型
  • 可变参数个数

一个基本的设计原则是:仅仅当两个函数除了参数类型和参数个数不同以外。其功能完全相同的,此时才使用函数常在。

如果两个函数的功能不同,不应当使用重载,而应该使用一个名字不同的函数。

问题

  • 函数功能相同,但参数类型不同,python如何处理?

    • 根本不需要处理,因为python可以接受任何类型的参数,如果函数的功能相同,name不同的参数类型在python中很可能是相同的代码,没有必要做成两个不同的函数。
  • 函数功能相同,但参数个数不同,python如何处理?
    • 缺省参数,对那些缺少的参数设定为缺省参数即可解决问题。

14.新式类和旧式类

python3里的类全部都是新式类,这里有一个MRO问题,新式类是广度优先,旧式类是深度优先。

15.__new__和__init__的区别

__new__是一个静态方法,而__init__是一个实例方法。
__new__方法会返回一个创建的示例,而__init__什么都不返回
只有在__new__返回一个cls的实例时后面的__init__才能被调用。
当创建一个新实例时调用__new__,初始化一个实例时用__init__
__metaclass__是创建类时起作用,所以我们可以分别使用。
__metaclass__、__new__、__init__来分别在类创建,实例创建和实例初始化的时候做些手脚。

16.单例模式

class A(object):
def __new__(cls,*args,**kwargs):
if not hasattr(cls,'_instance'):
orig = super(A,cls)
cls._instance = orig.__new__(cls,*args,**kwargs)
return cls.__instance class MyClass(A):
a = 1

共享属性

创建实例时把所有实例的__dict__指向同一个字典,这样他们具有相同的属性和方法。

class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob
class MyClass2(Borg):
a = 1
装饰器版本
def singleton(cls, *args, **kw):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance
@singleton
class MyClass:
pass

python面试题总结的更多相关文章

  1. Python面试题 —— 获取列表中位数

    中位数是一个可将数值集合划分为相等的上下两部分的一个数值.如果列表数据的个数是奇数,则列表中间那个数据就是列表数据的中位数:如果列表数据的个数是偶数,则列表中间那2个数据的算术平均值就是列表数据的中位 ...

  2. python公司面试题集锦 python面试题大全

    问题一:以下的代码的输出将是什么? 说出你的答案并解释. class Parent(object): x = 1 class Child1(Parent): pass class Child2(Par ...

  3. 【Python】【面试必看】Python笔试题

    前言 现在面试测试岗位,一般会要求熟悉一门语言(python/java),为了考验求职者的基本功,一般会出 2 个笔试题,这些题目一般不难,主要考察基本功.要是给你一台电脑,在编辑器里面边写边调试,没 ...

  4. Python面试题整理-更新中

    几个链接: 编程零基础应当如何开始学习 Python ? - 路人甲的回答 网易云课堂上有哪些值得推荐的 Python 教程? - 路人甲的回答 怎么用最短时间高效而踏实地学习 Python? - 路 ...

  5. python 面试题4

    Python面试题 基础篇 分类: Python2014-08-08 13:15 2071人阅读 评论(0) 收藏 举报 最近,整理了一些python常见的面试题目,语言是一种工具,但是多角度的了解工 ...

  6. 一道Python面试题

    无意间,看到这么一道Python面试题:以下代码将输出什么? def testFun():    temp = [lambda x : i*x for i in range(4)]    return ...

  7. 很全的 Python 面试题

    很全的 Python 面试题 Python语言特性 1 Python的函数参数传递 看两个例子:           Python   1 2 3 4 5 a = 1 def fun(a):      ...

  8. SQL + Python 面试题:之二(难度:中等)

    SQL + Python 面试题:之二(难度:中等)

  9. Python面试题之一:解密

    Python面试题之一: 说明:就是Python工程师面试题 一.字典转换与正则提取值 1:key与Value交换 a = {'a':1,'b':2} print({value:key for key ...

  10. 震惊!几道Python 理论面试题,Python面试题No18

    本面试题题库,由公号:非本科程序员 整理发布 第1题: 简述解释型和编译型编程语言? 解释型语言编写的程序不需要编译,在执行的时候,专门有一个解释器能够将VB语言翻译成机器语言,每个语句都是执行的时候 ...

随机推荐

  1. 国产网络损伤仪SandStorm -- 只需要上下拖拽能调整链路规则顺序

    国产网络损伤仪SandStorm(弱网络测试)可以模拟出带宽限制.时延.时延抖动.丢包.乱序.重复报文.误码.拥塞等网络状况,在实验室条件下准确可靠地测试出网络应用在真实网络环境中的性能,以帮助应用程 ...

  2. 给你的SpringBoot项目定制一个牛年专属banner吧

    新春快乐,牛年大吉! 新的一年是牛年,在SpringBoot项目里自定义了一个牛年相关的banner,看起来可真不错. 上面是自己制作的一个banner,相关的ASCII字符在文末. SpringBo ...

  3. Linux内核4.19.1编译

    linux内核编译 1.1 大致步骤 下载linux内核4.19.1 官网链接: https://www.kernel.org/ 官网下载经常速度太慢,无法下载,提供另一个链接: http://ftp ...

  4. Pymongo 笔记

    Pymongo 1.MongoDB概念 MongoDB是一种非关系型数据库(NoSQL),MongoDB数据存储于内存,内存不足则将热度低数据写回磁盘.存储的数据结构为文档.每个数据库包含若干集合(c ...

  5. CVE-2019-13272:Linux本地内核提权漏洞复现

    0x00 简介 2019年07月20日,Linux正式修复了一个本地内核提权漏洞.通过此漏洞,攻击者可将普通权限用户提升为Root权限. 0x01 漏洞概述 当调用PTRACE_TRACEME时,pt ...

  6. 7816协议时序和采用UART模拟7816时序与智能卡APDU指令协议

    7816时序 7816时一个比较早的老通讯时序了,最近项目上需要用UART模拟所以,简单学习时序. 时序比较简单,熟悉UART的一眼看着就像是串口的时序,只是他没有停止位,取而代之的就是保护时间gur ...

  7. Github markdown页面内跳转

    基本操作: 请看这里 最典型的就是[alt_content](#jump) 但有时, jump是不太好直接看出来的, 比如下面这个标题, 格式复杂, 那如何获取相应的jump呢? 在Github中, ...

  8. Node.js 实战 & 最佳 Express 项目架构

    Node.js 实战 & 最佳 Express 项目架构 Express Koa refs https://github.com/xgqfrms/learn-node.js-by-practi ...

  9. ServerLess & MongoDB Atlas & REST API

    ServerLess & MongoDB Atlas & REST API ServerLess, Nodejs, MongoDB Atlas cloud 构建 REST API ht ...

  10. how to fetch html content in js

    how to fetch html content in js same origin CORS fetch('https://cdn.xgqfrms.xyz/') .then(function (r ...