模块

使用模块import 模块名。有的仅仅导入了某个模块的一个类或者函数,使用from 模块名 import 函数或类名实现。为了避免模块名冲突。Python引入了按文件夹来组织模块的方法,称为包(Package)

则在a文件夹下的b.py模块名就是a.b。a文件夹下必须有一个文件__ini__.py。哪怕是文件内容是空。否则a就成了普通文件夹。

标准模块文件模板:

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 'a test module' #不论什么模块的第一个字符串都被视为模块的文档凝视 __author__ = 'Your Name' ...
def f():
... if __name__ == '__main__': #从其它地方导入模块,if不会通过。因此能够用来在命令行下进行測试
f()
  • 模块中的非公开函数前缀_。如def _private_1():
  • 能够被直接引用的特殊变量一般用__argname__这样的前后各两个下划线的形式来表示。自定义的公开函数或变量一般就用普通的形式def f,不用这样的下划线形式。
  • 须要注意的是。Python并没有一种方法能够全然限制訪问private函数或变量。因此这个得靠自觉了

第三方模块能够使用pip安装pip install numpy。它会从python的官方站点自己主动下载和安装。

也能够自己下载下来之后安装。

面向对象编程

类语法

class Student(object):
pass

object是默认父类名称。实例的创建使用tom = Student()。作为动态语言,Python支持自由给tom绑定类外的新属性tom.name = 'Tom'

假设有须要在创建实例时绑定的属性。一般写在类中的__ini__函数中:

def __ini__(self, arg1, arg2):
self.__arg1 = ...
self.arg2 = ...

__ini__的第一个參数永远是self,会自己主动传入。

有了这样的__ini__。创建实例时就须要传入arg1arg2參数。__arg1的两个前下划线表明这是一个私有属性,不能被外部訪问。

鸭子类型:仅仅要看起来像鸭子。跑起来像鸭子,那就能够看做鸭子

Python的动态性也体如今继承的上。假设有个函数中调用了某类的方法,仅仅要传入的对象也有这种方法,都能够运行,而和这个对象是不是该类或该类子类的实例无关。

获取对象信息

  • 获取对象的信息能够使用type(),同一时候假设import types。还能够使用type(对象) == types.type模块中的常量函数类型来推断一个对象是否是某种详细函数类型。

  • isinstance(对象,类)的推断方法则假设该对象是參数中类的父类也返回True。能用type推断的基本类型都能够使用isinstance,第二个參数也能够是个list。仅仅要满足是元素之中的一个就返回True。

  • dir()能够将一个对象的全部属性和方法都返回

  • 当不知道对象细节时,能够使用hasattr(obj, 'arg')得到obj是否有arg属性或方法;getattr(obj, 'arg')返回属性或方法;setattr(obj, 'arg', value)设置属性或方法(没有则直接添加)

面向对象高级编程

使用__slots__

由于Python是动态语言。因此能够任意为类、实例绑定属性或者方法。绑定方法要用到from types import MethodTypes.f = MethodType(f, s)将方法f绑定到类或实例s上。同一时候要注意f的第一个參数要是self才干绑定。

假设想要限制实例的属性,就须要在定义类的时候定义一个特殊变量__slots__ = ('name1','name2')来限定给实例绑定的属性名仅仅能是name1或者name2。

辨析:

from types import MethodType

class Student(object):
__slots__ = ('name', 'sex', 'set_name', 'set_grade')
#同意绑定的在下文中称为内方法和内属性。 反之称为外方法和外属性# #内方法中绑定内属性
def set_name(self, name):
self.name = name #内方法中绑定外属性#
def set_grade(self, grade):
self.grade = grade #外方法中绑定外属性#
def set_score(self, score):
self.score = score #外方法中绑定内属性#
def set_sex(self, sex):
self.sex = sex tom = Student()
jane = Student()

(1)给实例绑定属性:

tom.name = 'Tom'    #正确。name是内属性
jane.grade = 98 #错误,grade是外属性。不能绑定
print(jane.name) #错误,未定义实例jane的name #第三句可见实例绑定的属性仅仅算各个实例自己的

(2)给类绑定属性:

Student.name = 'name'    #内属性能够绑定
Student.grade = 0 #外属性也能够绑定,可见__slots__仅仅作用于实例 tom.name = 'Tom' #错误。可见通过这样的方法绑定的属性到实例中为仅仅读
print(jane.name) #输出为name

(3)给实例绑定方法:

tom.set_name = MethodType(set_name, tom)    #内方法,当中绑定内属性
tom.set_grade = MethodType(set_name, tom) #内方法。当中绑定外属性。调用方法时会报错
tom.set_score = MethodType(set_score, tom) #外方法。不可绑定
tom.set_sex = MethodType(set_name, tom) #外方法,不可绑定

(4)给类绑定方法

#绑定内方法
Student.set_name = MethodType(set_name, Student) tom.name = 'Tom'
print(jane.name) #报错,可见在调用方法绑定内属性之前。“实例.属性 =”事实上回到了第一种辨析的情况 tom.set_name('Tom')
jane.set_name('Jane') #调用内方法,才将内属性绑定到了类
tom.name = 'Tom' #报错。可见上一句绑定的属性和(3)中同样。仅仅读。 仅仅能通过类方法改动
print(jane.name)
print(tom.name) #输出也是Jane,可见通过类方法改动的属性是类属性,各实例的相应属性都是最后一次调用类方法之后的属性值 #绑定内方法,当中绑定外属性
Student.set_grade = MethodType(set_grade, Student)
tom.set_grade(4) #调用方法绑定了外属性
tom.grade = 4 #类属性仅仅读。不可直接改动
print(tom.grade) #实例拥有了外属性,只是是类属性,仅仅读,仅仅能通过类方法改动

剩下的两种情况不再赘述,由于__slots__不限制类,因此不论什么方法和属性都能够被绑定。仅仅只是通过调用方法绑定的属性是仅仅读的,仅仅能通过调用方法改动,不能在实例中直接使用.赋值改动通过以上辨析,总结例如以下:

__slots__仅仅限制实例的方法或属性绑定,不限制类。

对类绑定的方法和属性都能够在实例中调用,但类属性在实例中是仅仅读的,它的值为最后一次调用方法或通过类.属性=赋值的结果,不能在实例中用实例.属性=改动。

使用@property

当须要改动属性时。为了能够检查參数,一般调用方法来设置属性值。

但这样的话就略显麻烦。

这时候@property装饰器就起作用了。

@property
def name(self):
return self._name @name.setter #假设不用下面的部分,则name就变成了仅仅读属性
def name(self,value):
...类型检查等
self._name = value

注意属性_name一定要有下划线来区分属性和方法,否则名字同样变成了方法。上面的代码就成了递归。会报现递归次数溢出错误

多重继承

假设继承的多个父类都有同样的方法,则以第一个为准,后面几个父类的该方法不会起作用。

定制类

诸如__slots__这样的两端都有两个下划线的变量或者函数是有特殊用途的,因此能够通过定义这类对象来对类进行定制

__str__(self):当运行print(类)时,程序会打印出属性和内存地址,假设想要打印出特定的内容。则能够定义一个__str__方法,输出特定的内容。

假设不用print而是直接调用类名输出信息。则须要定义__repr__()方法。简单的一种定义方法就是__repr__ = __str__高速定义。

__iter__(self):假设想要迭代一个类则须要定义__iter__方法返回self。然后再定义一个__next__(self)方法运行迭代中要做的事情

__getitem__(self, n):把类变成像list那样能够按下标取元素操作。

__getitem__下返回元素值。假设要实现切片等功能。还要再对这个函数进行进一步的细化,比方推断传入的參数是否是slice等一系列兴许操作。

同样地,将类变为像dict那样,使用__setitem__。使用__delitem__删除元素。

以上的这些方法将类变成list或dict的“鸭子”,使类能够像list或dict那样操作。

__getattr__(self, attr):返回动态属性或方法。

这个函数下边对attr进行推断。从而绑定规定的属性或者方法。绑定属性返回属性值。绑定方法则返回lambda函数。

假设没有不论什么限制,显然不论什么属性或方法都能够绑定。这时候假设返回自身,则就实现了链式调用。利用这一点构造一个针对不同API的SDK。下面的代码就实现了一个GitHub的API的URL输出:

class Chain(object):

    def __init__(self, path =''):
self._path = path def __getattr__(self, path):
return Chain('%s/%s' %(self._path, path)) def __call__(self,name):
return Chain('%s/:%s' %(self._path, name)) def __str__(self):
return 'GET ' + self._path print(Chain().users('hermanncain').repos) #输出为GET /users/:hermanncain/repos

__call__(self):调用实例自身。

即调用s()时运行__call__(self)。也能够使用__call__(self, *args, **kw)来传递參数,则调用s(*args, *kw)时运行当中的内容。这样模糊了类和实例的界限。

枚举类

from enum import Enum

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 

'Oct', 'Nov', 'Dec'))

for name, member in Month.__member__.items():
print(name, '=>', member, ',', member.value)

value为枚举成员相应的int值,默认从1開始

还有一种从Enum派生的自定义枚举类。语法就和C++中的枚举类型有些像了:

from enum import Enum, unique

@unique
class Weekday(Enum):
Sun = 0
Mon = 1
...

@unique装饰器用于检查反复值。

对枚举类的成员有下面几种引用方法:

print(Weekday.Sun)
print(Weekday['Sun'])
print(Weekday(1))
#以上的输出都是Weekday.Sun print(Weekday.Sun.value)
#输出0

元类*

使用type()创建类

动态语言的函数和类的定义是在运行时动态创建的。

写一个a.py的模块。在模块里定义class A,然后在主程序中from a import A,加载模块时运行模块全部语句,结果就是动态创建出一个A的class。type(A)返回值是typetype(A的实例)的返回值则是class '__main__'.A

可是type()也能够用于动态创建类。实际上Python解释器遇到class定义时,也是使用type()动态地将该类创建出来的:

def f(self, ...):
... A = type('A', (object,), dict(af = f)

这样就动态创建了一个A类。父类是object(注意多重继承父类放在tuple里。假设仅仅有一个父类则tuple仅仅有一个元素,逗号不可少)。而且有一个名为af的方法。

metaclass元类*

类相当于元类的实例。metaclass是Python面向对象里最难理解,也是最难使用的魔术代码。一般用不到

*这部分内容先略过,等到用到的时候依据实例来整理

Python学习笔记(五)OOP的更多相关文章

  1. python学习笔记五 模块上(基础篇)

    模块学习 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要 ...

  2. Python学习笔记五

    一. 递归 递归函数: def a (): print ("from b") b() def b(): print("from a ") a() a() 递推和 ...

  3. Python学习笔记五:错误与异常

    一:常见异常与错误 BaseException 所有异常的基类SystemExit 解释器请求退出KeyboardInterrupt 用户中断执行(通常是输入^C)Exception 常规错误的基类S ...

  4. python学习笔记(五):装饰器、生成器、内置函数、json

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...

  5. Python学习笔记五(读取提取写入文件)

    #Python打开读取一个文件内容,然后写入一个新的文件中,并对某些字段进行提取,写入新的字段的脚本,与大家共同学习. import os import re def get_filelist(dir ...

  6. Python学习笔记(五)函数和代码复用

    函数能提高应用的模块性,和代码的重复利用率.在很多高级语言中,都可以使用函数实现多种功能.在之前的学习中,相信你已经知道Python提供了许多内建函数,比如print().同样,你也可以自己创建函数, ...

  7. python学习笔记五 模块下(基础篇)

    shevle 模块 扩展pickle模块... 1.潜在的陷进 >>> import shelve>>> s = shelve.open("nb" ...

  8. python学习笔记五--文件

    任何情况下文本文件在Python里均是字符串模式. 一.创建一个文件,并写入: 函数open(文件名,w) 二.打开一个文件,并读取: 函数open(文件名,r),“r”是默认值,可以不用写 三.使用 ...

  9. Python学习笔记五--条件和循环

    5.1 if语句 没什么好说,if语句语法如下: if expression: expr_true_suit 5.1.1多重条件表达式 单个if语句可以通过布尔操作符and,or,not实现多重条件判 ...

  10. Python学习笔记五,函数及其参数

    在Python中如何自定义函数:其格式为 def 函数名(函数参数): 内容

随机推荐

  1. Livepool

    LivePool Fiddler Like cross platform debugging proxy for web developers base on NodeJS LivePool 是一个基 ...

  2. centos7 nginx安装 及MySQL-python

    1.pip install MySQL-python 出错问题 pip install -r requirement.txt 发现安装MySQL-python 出错,更新setuptools也没用 解 ...

  3. How do I add elements to a Scala List?

    Scala List FAQ: How do I add elements to a Scala List? This is actually a trick question, because yo ...

  4. filebeat+kafka+SparkStreaming程序报错及解决办法

    // :: WARN RandomBlockReplicationPolicy: Expecting replicas with only peer/s. // :: WARN BlockManage ...

  5. dp之区间:最大k乘积

    题目:给你一个n(1<=n<=15)位数,求将它分成m段,用m-1个*连接起来的最大乘积....... 思路:定义dp[i][j]为将前i位数分成j段的最大乘积,那么dp[i][j]==m ...

  6. c# 操作Word总结【转】

    http://www.cnblogs.com/eye-like/p/4121219.html 在医疗管理系统中为保存患者的体检和治疗记录,方便以后的医生或其他人查看.当把数据保存到数据库中,需要新建很 ...

  7. dubbo2.5.3注解版

    1.环境      在机器192.168.0.4机器上安装了zookeeper,用于dubbo的服务注册,安装教程在另外一篇博客 http://www.cnblogs.com/520playboy/p ...

  8. C语言 · 前10名

    算法提高 前10名   时间限制:1.0s   内存限制:256.0MB      问题描述 数据很多,但我们经常只取前几名,比如奥运只取前3名.现在我们有n个数据,请按从大到小的顺序,输出前10个名 ...

  9. warning: assignment from incompatible pointer type [enabled by default]

    kernel 编译产生这个警告的原因是 不兼容指针类型的赋值 这个原因很有可能是因为返回值和正在接受这个指针类型名不相同. // vim arch/arm/mach-omap2/usb-host.c ...

  10. MySQL 源代码scr.rpm安装的一点注意事项

    rpm安装包通常为二进制包(Binary)以及源代码包(Source)两种形式. 在使用源代码方式安装MySQL的时候,官方站点上下载的源代码包通常为scr.rpm格式,而不是直接的tar包.对此,须 ...