您的位置:首页 > 编程语言 > Python开发

Python面向对象学习笔记

2017-02-14 20:23 811 查看
视频课程《三-Python高级自动化开发工程师微职位:面向对象

subprocess模块
用途:如在Linux上调用windows的命令,需要获取命令的输出结果,而不是python代码的结果

与os.system的区别
输出命令结果到屏幕,返回值是Python代码运行的结果
subprocess把命令运行的结果和Python代码运行的结果都以元组形式返回,依次读取相应的值即可获得所需数据

Python2中类似的command

os.system("dir")  # 返回状态

os.popen("dir").read()  # 获取结果,但不明确"dir"的运行状态

# Linux上支持的比较好
import commands
comands.getstatusoutput("dir") # 以元组形式返回状态值和命令运行的结果

# Python3.5后出现的方法
import subprocess
subprocess.run(["df","-h"]) # 形式1
subprocess.run("df -h | grep sda1", shell=True) # 形式2

# Python3.5前的方法
subprocess.call(["ls", "-a"]) # 类似与os.system("ls")
# 不需要获得命令运行结果,只需指导代码运行状态时
subprocess.check_call(["ls", "-l"]) # 返回0或者异常
subprocess.getstatusoutput("ls bin/ls") # 返回(0, "/bin/ls")
subprocess.output("ls bin/ls") # 返回/bin/ls"
subprocess.check_output(["ls", "-a"]) # 返回res,如:b'/bin/ls',并非打印
底层封装subprocess.popen()方法,返回到res对象中同时还能细分stderror
#res中只包含stdout的输出,从subprocess.PIPE读取而得
res = subprocess.Popen("ifconfig | grep 192", shell=True, stdout=subprocess.PIPE)
res.stdout.read() # 获得stdout的数据
res = subprocess.Popen("ifconfig haha | grep 192, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
res.stdout.read() # 获取运行结果
res.stderr.read() # 获取错误信息
注意,每次调用相当于启动一个新的shell

res = subprocess.Popen("sleep 10; echo 'hi'", shell=True, stdout=subprocess.PIPE)
res.poll() # 在命令执行完成后返回0,否则一直返回None,这是一个有趣的方法,注意理解
#或者可以使用阻塞的方法
res.wait() # 等待命令执行完,返回0
res.terminate()# 中止执行命令

res = subprocess.Popen("python3", shell=True, stdout=process.PIPE, stdin=subprocess.PIPE)
res.stdin.write("print(1)") # 启动过程中写入数据
res.communicate(timeout=10) # 等待结果
例子:

# python中执行“sudo -S apt-get install vim”注意这个过程需要输入密码
subprocess.Popen("sudo -S apt-get install vim", shell=True, stdout=subprocess.PIPE) # 出错
# 明确命令“echo '1234' | sudo -S apt-get install vim”


面向对象
OOP利用类和对象对世界进行描述,使得程序维护和扩展变得简单,提高开发效率,代码容易理解。
Class类
抽象出属性的描述和方法。抽象的意义在于化繁为简,更有效率的描述信息。

Object对象
类的实例,对象真正存储着属性的值(通常意义上,类属性等除外)
Encapsulation封装
在类中对数据赋值、内部调用,外部调用不必也不能对类内进行修改访问。(对外部隐藏对象的工作细节)

Inheritance继承
代码复用,以普通类为基础建立专门的类
Polymorphism多态
对不同类的对象使用相同的操作,它们会有不同的结果。

“重复代码是可耻的行为”
“代码需要经常改动”
定义
原则:可读性好,易扩展
class Role(object):
def __init__(self, name, role, value, money):
self.name = name
self.role = role
self.life_value = value
self.money = money

def shot(self):
print("shooting...")

def got_shot(self):
print("ah..., I got shot...")

def buy_gun(self, gun):
print("just bought %s", gun)

# Python自动调用__del__方法,当对象内存被回收时,将会调用这个方法
def __del__(self):
print("del ...run")
Python类定义的写法,其实就是执行代码块。
特性
普通属性(成员变量或字段)

在__init__()中确定,可以被直接访问和修改,也可以通过方法访问和修改。属于对象的,不同对象不能直接访问。

私有属性
形如self.__heart,obj.__heart无法外部访问,但实际上可以通过如下方法进行访问

def get_heart(self): # 通过方法访问
return self.__heart
obj._Role__heart # 通过对象引用直接访问和修改
公有属性
类的所有实例都可以访问的属性,可以理解为类的属性。如果通过对象的引用修改了同名的公有属性,相当于对象添加了一个自己的普通属性。所以类的属性只能通过类名.nationality来修改。

方法
方法也是公有的,要注意理解。之所以要用对象的引用调用,因为定义时要通过self传递参数。

def shot2(self):
print("run my own shot method, self.name
r1.shot = shot2
r1.shot(r1)
r2.shot()
# 注意,r1对象shot方法对应的方法已经被外部定义的shot2方法替换,并且需要手动传递参数
# r2则使用的时原来的参数
析构方法
__del__(self),对象的引用被清理时会被自动调用,相当于“回调方法”在自定义对象被清理时,手动清理需要清理的变量。

关于继承机制
继承机制能够让子类或派生类在使用父类(基类)的功能,并且在无需编写原来功能代码的情况下对这些功能进行扩展。继承机制的实现有以下三种方式:

单继承
先继承再重写

class Person(object):
person_count = 0
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex

def talk(self):
print("Person is talking.")

def inroll(self):
# 类的计数器要使用类名调用
Person.person_count += 1

def tell(self):
print("%s info" % self.name)
for k,v in self.__dict__.items():
print(k, v)

class BlackPerson(Person):
def __init__(self, name, age, sex, strength):
# 这里先继承了父类,然后重写了方法,并调用了父类的方法
#  Person.__init__(self, name, age, sex)  # 经典类写法

# 新式类写法,注意self参数的位置,以及理解调用机制
super(Person, self).__init__(name, age, sex)
self.strength = strength
print(self.name, self,age, self, sex)

def talk(self):
# 同名方法,子类会覆盖父类的方法
print("Black person is talking")

def walk(self):
# 子类对父类的拓展
print("Black is walking.")
多继承

再Python2和Python3里类的寻找路径是有区别的,Python2是深度优先(是否区分经典和新式?),Python3是广度优先。

# 此代码在windows下Python3环境运行
# 无论O是新式或经典写法,查询路径都是广度优先,很可能Python3内部实现已经全部归于新式类
class O(object):
def __init__(self):
print("init O")
self.n = "O"

class A(O):
pass
# def __init__(self):
#     print("init A")
#     self.n = "A"

class B(O):
# pass
def __init__(self):
print("init B")
self.n = "B"

class C(A, B):
pass

cc = C()
print(cc.n)
但是利用在线解释器,使用Python2.7环境下会有区别,如图:







可以看出区别,Python2.7环境下,新式类广度优先,经典类深度优先(注意O的写法)
广度优先和深度优先的临界点



只有查找到A0时才会判断使用深度优先还是广度优先,如果再A0时查找O则是深度优先,如果去查找B1则是广度优先!
组合

关于多态

接口重用,通俗讲,就是通过父类调用子类的方法,体现出不同的形态。
class Animal(object):
def talk(self):
raise NotImplementedError("未实现该方法,报错")

def real_talk(self):
print(self.talk())

class Cat(Animal):
def talk(self):
return "Meow!"

class Dog(Animal):
def talk(self):
return "Woof,Woof!"

c = Cat()
d = Dog()
c.real_talk()
d.real_talk()


补充
类,对象的关系
ssh应用案例:
# 整个过程还是抽象,抽象,抽象
class SSH:
def __init__(self, host, port, pwd, username):
self.host = host
self.port = port
self.qwd = pwd
self.username = username

def connection(self):
# 创建链接
#  self.conn = 链接对象()
pass

def close(self):
# 关闭链接
pass

def upload(self):
pass

def com(self):
pass

obj = SSH()


函数保存在类里,字段保存在对象里。
静态属性(共有属性)
封装的理解:
类封装了字段名和方法,“抽象”是封装的方法论;
对象封装了字段的值,也就是类的实体;
类方法寻找的顺序,要注意F2的a1方法里调用self.a2(),self.a2()寻找的起点仍然是F3
class F1:
def __init__(self):
print("F1")

def a1(self):
print("F1a1")

def a2(self):
print("F1a2")

class F2(F1):
def __init__(self):
print("F2")

def a1(self):
self.a2()
print("F2a1")

def a2(self):
print("F2a2")

class F3(F2):
def __init__(self):
print("F3")

def a2(self):
print("F3a2")

obj = F3()
obj.a1() # F3a2 F2a1


静态方法 @staticmethod
保存在类里
class F1:
def __init__(self):
print("F1")

@staticmethod
def a1(): # 可以没有self参数,也可以设定任意参数
print("F1a1")

F1.a1() # 通过类来访问
Python是否有“静态变量”?
Python是动态语言,它的类严格讲没有静态变量,不过从特性上来讲,类变量可以称为“静态变量”
子类调用父类构造方法

# 两种方法可以实现
class A:
def __init__(self):
self.hungry = True

class B:
def __init__(self):
A.__init__(self) # 方法一,调用父类的未绑定构造方法
# super(A, self).__init__()  # 方法二,super函数返回的引用相当于父类对象的引用,可以直接调用。
self.sound = "Squawk!"
两种方法均可以调用,通过super函数调用的写法是新式类的写法,而利用父类的未绑定构造方法并传入self引用的调用方法是“传统阵营”的写法。所以使用super更被推荐。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息