深入Python函数编程的一些特性
绑定
细心的读者可能记得我在 第 1 部分的函数技术中指出的限制。特别在 Python 中不能避免表示函数表达式的名称的重新绑定。在 FP 中,名称通常被理解为较长表达式的缩写,但这一说法暗示着“同一表达式总是求出相同的值”。如果标记的名称重新被绑定,这一暗示便不成立。例如,让我们定义一些在函数编程中要用到的快捷表达式,比如:
清单 1. 以下 Python FP 部分的重新绑定要造成故障
>>> car = lambda lst: lst[0] >>> cdr = lambda lst: lst[1:] >>> sum2 = lambda lst: car(lst)+car(cdr(lst)) >>> sum2(range(10)) 1 >>> car = lambda lst: lst[2] >>> sum2(range(10)) 5
不幸的是,完全相同的表达式 sum2(range(10)) 在程序中的两处求得两个不同的值,即使该表达式自身并没有在其参数中使用任何可变变量。
幸运的是, functional 模块提供了称为 Bindings 的类(向 Keller 提议)来防止这样的重新绑定(至少在偶然情况下,Python 不会阻止一心想要解除绑定的程序员)。然而使用 Bindings 需要一些额外的语法,这样意外就不太容易发生。在 functional 模块的示例中,Keller 将 Bindings 实例命名为 let (我假定在 ML 家族语言的 let 关键词的后面)。 例如,我们会这样做:
清单 2. 具有安全重新绑定的 Python FP 部分
>>> from functional import * >>> let = Bindings() >>> let.car = lambda lst: lst[0] >>> let.car = lambda lst: lst[2] Traceback (innermost last): File "<stdin>", line 1, in ? File "d:\tools\functional.py", line 976, in __setattr__ raise BindingError, "Binding '%s' cannot be modified." % name functional.BindingError: Binding 'car' cannot be modified. >>> car(range(10)) 0
很明显,真正的程序必须做一些设置来捕获“绑定错误”,而且他们被抛出也避免了一类问题的出现。
与 Bindings 一起, functional 提供 namespace 函数从 Bindings 实例中获取命名空间(实际上是个字典)。如果希望在 Bindings 中定义的(不可变)命名空间中运算一个表达式,这非常容易实现。Python 的 eval() 函数允许在命名空间中进行运算。 让我们通过一个示例来弄清楚:
清单 3. 使用不可变命名空间的 Python FP 部分
>>> let = Bindings() # "Real world" function names >>> let.r10 = range(10) >>> let.car = lambda lst: lst[0] >>> let.cdr = lambda lst: lst[1:] >>> eval('car(r10)+car(cdr(r10))', namespace(let)) >>> inv = Bindings() # "Inverted list" function names >>> inv.r10 = let.r10 >>> inv.car = lambda lst: lst[-1] >>> inv.cdr = lambda lst: lst[:-1] >>> eval('car(r10)+car(cdr(r10))', namespace(inv)) 17
闭包
FP 中有个有趣的概念 -- 闭包。实际上,闭包对许多开发人员都非常有趣,即使在如 Perl 和 Ruby 这样的无函数语言中也都包括闭包这一功能。而且,Python 2.1 目前正想加入词汇范围限制功能,这一功能将提供闭包的大部分功能。
什么 是闭包呢? Steve Majewski 最近在 Python 新闻组提供了对这一概念的很好描述:
对象是附带过程的数据……闭包是附带数据的过程。
闭包就象是 FP 的 Jekyll 对于 OOP 的 Hyde (角色或者也可能对调)。闭包类似对象示例,是一种将一大批数据和功能封装在一起的一种方式。
让我们回到先前的地方了解对象和闭包解决什么问题,同时了解一下问题如果没有这两样是如何解决的。函数返回的结果往往是由其计算中使用的上下文决定的。最常见的 -- 也可能是最明显的 -- 指定上下文的方法是向函数传递某些参数,通知函数处理什么值。但有时候“背景”和“前景”参数有着本质的区别 -- 在这特定时刻函数正在处理的和函数为多段潜在调用而“配置”之间的区别。
当把重点放在前景的时候,有许多处理背景的方法。其中一种是简单“咬出子弹”的方法,在每次调用的时候传递函数需要的每一个参数。这种方法通常在调用链中,只要在某些地方有可能需要值,就会传递一些值(或带有多成员的结构)。以下是一个小示例:
清单 4. 显示 cargo 变量的 Python 部分
>>> defa (n): ... add7 = b(n) ... return add7 ... >>> defb (n): ... i = 7 ... j = c(i,n) ... return j ... >>> defc (i,n): ... return i+n ... >>> a(10) # Pass cargo value for use downstream 17
在 cargo 示例的 b() 中, n 除了起到传递到 c() 的作用外并无其他作用。另一种方法将使用全局变量:
清单 5. 显示全局变量的 Python 部分
>>> N = 10 >>> defaddN (i): ... global N ... return i+N ... >>> addN(7) # Add global N to argument 17 >>> N = 20 >>> addN(6) # Add global N to argument 26 全局变量 N 在任何希望调用 addN() 的时候起作用,但没有必要明确地传递全局背景“上下文”。另一个更 Python 专用的技术是将一个变量在定义时“冻结”入一个使用默认参数的函数: 清单 6. 显示冻结变量的 Python 部分 >>> N = 10 >>> defaddN (i, n=N): ... return i+n ... >>> addN(5) # Add 10 15 >>> N = 20 >>> addN(6) # Add 10 (current N doesn't matter) 16
冻结变量本质上就是闭包。某些数据被“隶属”于 addN() 函数。对于完整的闭包,当定义 addN() 的时候,所有的数据在调用的时候都将可用。然而,在这个示例(或者许多更健壮的示例)中,使用默认的参数就能简单的够用了。 addN() 从未使用的变量并不会对其计算造成影响。
接着让我们来看一个更接近真实问题的 OOP 方法。年份的时间是我想起了那些“会见”风格的收集各种数据的税收程序 -- 不必有特定的顺序 -- 最终使用全部数据来计算。让我们创建一个简单的版本:
清单 7. Python 风格的税收计算类/示例
class TaxCalc: deftaxdue (self): return (self.income-self.deduct)*self.rate taxclass = TaxCalc() taxclass.income = 50000 taxclass.rate = 0.30 taxclass.deduct = 10000 print "Pythonic OOP taxes due =", taxclass.taxdue()
在 TaxCalc 类(或其实例)中,能收集一些数据 -- 可以以任意顺序 -- 一旦获得了所需的所有元素,就能调用这一对象的方法来完成这一大批数据的计算。所有一切都在实例中,而且,不同示例携带不同的数据。创建多示例和区别它们的数据的可能性不可能存在于"全局变量"或"冻结变量"方法中。"cargo" 方法能处理这个问题,但对于扩展的示例来说,我们看到它可能是开始传递各种值的必要条件了。既然我们已讲到这,注意传递消息的 OPP 风格是如何处理的也非常有趣(Smalltalk 或 Self 与此类似,一些我使用的 OOP xBase 变量也是如此):
清单 8. Smalltalk 风格 (Python) 的税收计算
class TaxCalc: deftaxdue (self): return (self.income-self.deduct)*self.rate defsetIncome (self,income): self.income = income return self defsetDeduct (self,deduct): self.deduct = deduct return self defsetRate (self,rate): self.rate = rate return self print "Smalltalk-style taxes due =", \ TaxCalc().setIncome(50000).setRate(0.30).setDeduct(10000).taxdue()
用每个 "setter" 来返回 self 使我们能把“现有的”东西看作是每个方法应用的结果。这与 FP 闭包方法有许多有趣的相似点。
有了 Xoltar 工具包,我们就能创建具有所期望的合并数据与函数特性的完整的闭包,同时还允许多段闭包(nee 对象)来包含不同的包:
清单 9. Python 函数风格的税收计算
from functional import * taxdue = lambda : (income-deduct)*rate incomeClosure = lambda income,taxdue: closure(taxdue) deductClosure = lambda deduct,taxdue: closure(taxdue) rateClosure = lambda rate,taxdue: closure(taxdue) taxFP = taxdue taxFP = incomeClosure(50000,taxFP) taxFP = rateClosure(0.30,taxFP) taxFP = deductClosure(10000,taxFP) print "Functional taxes due =",taxFP() print "Lisp-style taxes due =", \ incomeClosure(50000, rateClosure(0.30, deductClosure(10000, taxdue)))()
我们定义的每一个闭包函数都携带了函数范围内定义的任何值,然后将这些值绑定到函数对象的全局范围。然而,函数的全局范围看上去不必与实际模块的全局范围相同,同时与不同闭包的“全局”范围也不相同。闭包只是简单地“携带数据”。
在示例中,我们使用了一些特殊函数在闭包范围 (income、deduct、rate) 内放入了特定绑定。修改设计以在范围内放入任何绑定也非常简单。我们还可以在示例中使用具有细微差别的不同函数风格,当然这只是为了好玩。第一个成功的将附加值绑定入闭包范围内;使 taxFP 成为可变,这些“加入到闭包”的行可以任意顺序出现。然而,如果要使用如 tax_with_Income 这样的不可变名称,就必须将绑定行按照一定顺序排列,然后将前面的绑定传递到下一个。无论如何,一旦必需的一切被绑定入闭包的范围内,我们就调用 "seeded" 函数。
第二种风格看上去更接近 Lisp,(对我来说更像圆括号)。如果不考虑美观,第二种风格中发生了二件有趣的事情。第一件是名称绑定完全被避免了。第二种风格是一个单一表达式而不使用语句(请参阅 第 1 部分,讨论为什么这样会有问题)。
其它有关“Lisp 风格”闭包使用的有趣例子是其与上文提到的“Smalltalk 风格”消息传递方法有多少类似。两者累积了值和调用 taxdue() 函数/方法(如果没有正确的数据,两者在这些原始版本中都将报错)。“Smalltalk 风格”在每一步之间传递对象,而“Lisp 风格”传递一个连续。但若是更深一层理解,函数和面向对象编程大部分都是这样。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











PHP와 Python은 고유 한 장점과 단점이 있으며 선택은 프로젝트 요구와 개인 선호도에 달려 있습니다. 1.PHP는 대규모 웹 애플리케이션의 빠른 개발 및 유지 보수에 적합합니다. 2. Python은 데이터 과학 및 기계 학습 분야를 지배합니다.

CentOS 시스템에서 Pytorch GPU 가속도를 활성화하려면 Cuda, Cudnn 및 GPU 버전의 Pytorch를 설치해야합니다. 다음 단계는 프로세스를 안내합니다. CUDA 및 CUDNN 설치 CUDA 버전 호환성 결정 : NVIDIA-SMI 명령을 사용하여 NVIDIA 그래픽 카드에서 지원하는 CUDA 버전을보십시오. 예를 들어, MX450 그래픽 카드는 CUDA11.1 이상을 지원할 수 있습니다. Cudatoolkit 다운로드 및 설치 : NVIDIACUDATOOLKIT의 공식 웹 사이트를 방문하여 그래픽 카드에서 지원하는 가장 높은 CUDA 버전에 따라 해당 버전을 다운로드하여 설치하십시오. CUDNN 라이브러리 설치 :

Python과 JavaScript는 커뮤니티, 라이브러리 및 리소스 측면에서 고유 한 장점과 단점이 있습니다. 1) Python 커뮤니티는 친절하고 초보자에게 적합하지만 프론트 엔드 개발 리소스는 JavaScript만큼 풍부하지 않습니다. 2) Python은 데이터 과학 및 기계 학습 라이브러리에서 강력하며 JavaScript는 프론트 엔드 개발 라이브러리 및 프레임 워크에서 더 좋습니다. 3) 둘 다 풍부한 학습 리소스를 가지고 있지만 Python은 공식 문서로 시작하는 데 적합하지만 JavaScript는 MDNWebDocs에서 더 좋습니다. 선택은 프로젝트 요구와 개인적인 이익을 기반으로해야합니다.

Docker는 Linux 커널 기능을 사용하여 효율적이고 고립 된 응용 프로그램 실행 환경을 제공합니다. 작동 원리는 다음과 같습니다. 1. 거울은 읽기 전용 템플릿으로 사용되며, 여기에는 응용 프로그램을 실행하는 데 필요한 모든 것을 포함합니다. 2. Union 파일 시스템 (Unionfs)은 여러 파일 시스템을 스택하고 차이점 만 저장하고 공간을 절약하고 속도를 높입니다. 3. 데몬은 거울과 컨테이너를 관리하고 클라이언트는 상호 작용을 위해 사용합니다. 4. 네임 스페이스 및 CGroup은 컨테이너 격리 및 자원 제한을 구현합니다. 5. 다중 네트워크 모드는 컨테이너 상호 연결을 지원합니다. 이러한 핵심 개념을 이해 함으로써만 Docker를 더 잘 활용할 수 있습니다.

Minio Object Storage : Centos System Minio 하의 고성능 배포는 Go Language를 기반으로 개발 한 고성능 분산 객체 저장 시스템입니다. Amazons3과 호환됩니다. Java, Python, JavaScript 및 Go를 포함한 다양한 클라이언트 언어를 지원합니다. 이 기사는 CentOS 시스템에 대한 Minio의 설치 및 호환성을 간단히 소개합니다. CentOS 버전 호환성 Minio는 다음을 포함하되 이에 국한되지 않는 여러 CentOS 버전에서 확인되었습니다. CentOS7.9 : 클러스터 구성, 환경 준비, 구성 파일 설정, 디스크 파티셔닝 및 미니를 다루는 완전한 설치 안내서를 제공합니다.

CentOS 시스템에 대한 Pytorch 분산 교육에는 다음 단계가 필요합니다. Pytorch 설치 : 전제는 Python과 PIP가 CentOS 시스템에 설치된다는 것입니다. CUDA 버전에 따라 Pytorch 공식 웹 사이트에서 적절한 설치 명령을 받으십시오. CPU 전용 교육의 경우 다음 명령을 사용할 수 있습니다. PipinStalltorchtorchvisiontorchaudio GPU 지원이 필요한 경우 CUDA 및 CUDNN의 해당 버전이 설치되어 있는지 확인하고 해당 PyTorch 버전을 설치하려면 설치하십시오. 분산 환경 구성 : 분산 교육에는 일반적으로 여러 기계 또는 단일 기계 다중 GPU가 필요합니다. 장소

CentOS 시스템에 Pytorch를 설치할 때는 적절한 버전을 신중하게 선택하고 다음 주요 요소를 고려해야합니다. 1. 시스템 환경 호환성 : 운영 체제 : CentOS7 이상을 사용하는 것이 좋습니다. Cuda 및 Cudnn : Pytorch 버전 및 Cuda 버전은 밀접하게 관련되어 있습니다. 예를 들어, pytorch1.9.0은 cuda11.1을 필요로하고 Pytorch2.0.1은 cuda11.3을 필요로합니다. CUDNN 버전도 CUDA 버전과 일치해야합니다. Pytorch 버전을 선택하기 전에 호환 CUDA 및 CUDNN 버전이 설치되었는지 확인하십시오. 파이썬 버전 : Pytorch 공식 지점

파이썬은 자동화, 스크립팅 및 작업 관리가 탁월합니다. 1) 자동화 : 파일 백업은 OS 및 Shutil과 같은 표준 라이브러리를 통해 실현됩니다. 2) 스크립트 쓰기 : PSUTIL 라이브러리를 사용하여 시스템 리소스를 모니터링합니다. 3) 작업 관리 : 일정 라이브러리를 사용하여 작업을 예약하십시오. Python의 사용 편의성과 풍부한 라이브러리 지원으로 인해 이러한 영역에서 선호하는 도구가됩니다.
