模块

使用模块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. 每日英语:Some Chinese Students Stay Home to Get Ahead

    Li Shan's oldest son was the perfect candidate to join the throngs of Chinese students studying abro ...

  2. Spark的性能调优

    下面这些关于Spark的性能调优项,有的是来自官方的,有的是来自别的的工程师,有的则是我自己总结的. Data Serialization,默认使用的是Java Serialization,这个程序员 ...

  3. 通过Windows PowerShell远程管理计算机(精简版)

    现在你手中有一台server(主控端),你打算通过主控端远程管理多台server(被控端).这个过程可以通过Windows PowerShell来完成. 首先在被控端上以管理员权限打开PowerShe ...

  4. c++构造函数中调用构造函数---匿名对象再探

    #include<iostream> #include<string> using namespace std; class Copy_construction { publi ...

  5. Curator入门教程1

     简介 Curator是Netflix开源的一套ZooKeeper客户端框架. Netflix在使用ZooKeeper的过程中发现ZooKeeper自带的客户端太底层, 应用方在使用的时候需要自己处理 ...

  6. JS地毯式学习四

    1  窗口的位置 用来确定和修改 window 对象位置的属性和方法有很多. IE . Safari . Opera 和 Chrome都提供了 screenLeft 和 screenTop 属性,分别 ...

  7. 【WPF】使用Popup控件做浮窗/提示框

    需求:当鼠标移入某个区域时,弹出一个浮窗,以便用户进行下一步操作. 效果如下图: 当鼠标移入左上角的[多选显示]框内,出现下面的浮窗(悬浮在原UI之上).当在浮窗外点击鼠标左键时,隐藏该浮窗. 由于该 ...

  8. 泛型方法前为什么要加<T>

    package com.test05.myTest; class Fruit { public String toString() { return "Fruit"; } } cl ...

  9. linux实现防止恶意扫描 PortSentry

    linux实现防止恶意扫描 PortSentry   脚本 open 摘要: 端口做为服务器的大门安全很重要,当服务器运行很多服务时并向外提供服务,为防止有人恶意侦测服务器用途,可使用portsent ...

  10. find 命令一个命令多参数如何使用,????,perm

    [root@ob2 mytmp]# find -mtime -7 -type f \( -name "*.html" -o -name "*.tar.gz" \ ...