D07——C语言基础学PYTHON

时间:2022-02-06 06:09:01

C语言基础学习PYTHON——基础学习D07

20180826内容纲要:

  面向对象进阶学习

    1 静态方法

    2 类方法

    3 属性方法

    4 类的特殊成员方法(本节重点)

    5 反射(本节重点)

    6 异常(本节重点)

    7 动态导入模块 

    8 小结

    9 练习

0 类的创建(补充)

 class Foo(object):
def __init__(self,name):
self.name = name f =Foo("erha")
print(type(f))
print(type(Foo))
#输出结果:
# <class '__main__.Foo'>
# <class 'type'>
#发现f的类型是 类__main__.Foo,而Foo的类型是 类,类型

第一种方法

 #那么我们来看一下类的第二种创建方法
def func(self):
print("ni shi sha zi ba") Foo =type('Foo',(),{'func':func})
f =Foo()
f.func()
print(type(Foo))
'''
#这样看上和第一种有点不一样,因为没有构造函数还没有传参。那怎么操作呢? def func(self):
print("%s 今年 %s 岁了"%(self.name,self.age)) def __init__(self,name,age):
self.name = name
self.age = age Foo =type('Foo',(object,),{'func':func,
'__init__':__init__})
f =Foo('kanghui',22)
f.func()

第二种方法

类是由type类实例化产生的。

那么类的创建过程是怎样的呢?类中有一个属性 __metaclass__,其用来表示该类由谁来实例化创建

所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看类创建的过程。

metaclass 详解文章:http://*.com/questions/100003/what-is-a-metaclass-in-python

 #Author:ZhangKanghui

 class MyType(type):
def __init__(self,what,bases=None,dict=None):
print("MyType--------init")
super(MyType,self).__init__(what,bases,dict)
def __call__(self, *args, **kwargs):
print("MyType-------call")
obj = self.__new__(self,*args,**kwargs)
self.__init__(self,*args,**kwargs) class Foo(object):
__metaclass__ = MyType def __init__(self,name):
self.name = name
print("Foo-----init")
def __new__(cls, *args, **kwargs):
print("Foo----new")
print(object.__new__(cls)) #通过执行结果们可以看出return的返回值就是Foo的内存地址
return object.__new__(cls) #继承父类的new方法 #看不懂没关系,我们先来实例化一下看看都在干吗
obj =Foo("erha")
#执行结果:先执行new再执行init,这是为什么呢?
# Foo----new
# Foo-----init #这个时候我们把new中的return注释掉看一下执行结果。
#Foo----new 只执行了new,根本没有实例化。不信可以试一下 print(obj.name)
#所以new使用来创建实例的
#取消return的注释再执行一下
print(obj.name)

__new__&__metaclass

1 静态方法  @staticmethod

与类无关,不能访问类里的任何变量
只是名义上归类管理,但实际上静态方法里访问不了类和实例中的任何属性。只是名义上归类管理,但实际上静态方法里访问不了类和实例中的任何属性。

 #Author:ZhangKanghui
#先来大概认识一下staticmethod class Dog(object):
def __init__(self,name):
self.name = name
@staticmethod #这就跟类没有什么关系了,下面的这个只是一个貌似属于类的函数
def eat(self,food):
print("%s is eating %s" %(self.name,food)) d =Dog("二哈")
d.eat("baozi") #正常情况下是可以运行的,但是在eat函数上加一个@staticmethod在运行一下看看
#TypeError: eat() missing 1 required positional argument: 'food'
#这就跟类没有什么关系了,下面的这个只是一个貌似属于类的函数

静态方法

@staticmethod

通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法

上面的调用会出错误,说是eat需要一个self参数,但调用时却没有传递。

没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。

想让上面的代码可以正常工作有两种办法

1. 调用时主动传递实例本身给eat方法,即d.eat(d)

2. 在eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了。这就是静态方法。

 class Dog(object):
def __init__(self,name):
self.name = name @staticmethod
def eat():
print(" is eating")
d = Dog("二哈")
d.eat()

静态方法

@staticmethod

2 类方法  @classmethod      

只能访问类变量不能访问实例变量。
如果存在类变量和实例变量相同时,正常情况下会先访问实例变量,然后访问类变量。如果使用类方法则可以强制去访问类变量。

 #Author:ZhangKanghui

 class Dog(object):
n = "哈士奇"
def __init__(self,name):
self.name = name
@classmethod #这就跟类没有什么关系了,下面的这个只是一个貌似属于类的函数
def eat(self,food):
#print("%s is eating %s" %(self.name,food))
print("%s is eating %s" %(self.n,food)) d =Dog("二哈")
d.eat("baozi")
#这样直接运行会报错 AttributeError: type object 'Dog' has no attribute 'name'
#此时我们在类下面加一个类变量,然后用self.n调用它

类方法@classmethod

类方法通过@classmethod装饰器实现

此时,定义一个类变量执行以下试试看:

 class Dog(object):
name = "我是类变量"
def __init__(self,name):
self.name = name @classmethod
def eat(self):
print("%s is eating" % self.name) d = Dog("二哈")
d.eat() #执行结果 我是类变量 is eating

类方法@classmethod

3 属性方法  @property

属性方法的作用就是通过@property把一个方法变成一个静态属性

 #Author:ZhangKanghui
'''
class Dog(object):
def __init__(self,name):
self.name = name @property
def eat(self):
print("%s is eating %s" %(self.name,"baozi")) # d =Dog("二哈")
# d.eat
#这样就是属性方法,根据运行结果可以发现能够正常运行但是不能传参了
#那么如果想要传参怎么办呢? @eat.setter
def eat(self,food):
print("set to food:",food) d =Dog("二哈")
d.eat
d.eat ="roubaozi"
#此时发现虽然给d.eat这个静态方法赋值但是并没有将参数传进去。那怎么做呢?
'''
class Dog(object):
def __init__(self,name):
self.name = name
self.__food = None
@property
def eat(self):
print("%s is eating %s" %(self.name,self.__food)) @eat.setter
def eat(self,food):
#print("set to food:", food)
self.__food = food @eat.deleter
def eat(self):
del self.__food
print("删除了吗") d =Dog("二哈")
d.eat
d.eat ="roubaozi"
d.eat #那么属性可以删除吗?
#del d.eat 你会发现报错了 删不掉
#如果是真的想删除呢? 再加一个@eat.deleter
del d.eat

属性方法@property

综上,写一段代码:航班查询

1. 连接航空公司API查询

2. 对查询结果进行解析

3. 返回结果给你的用户

 #Author:ZhangKanghui

 class Flight(object):
def __init__(self,name):
self.flight_name = name
def checking_status(self):
print("checking flight %s status " % self.flight_name)
return 1
def flight_status(self):
status = self.checking_status()
if status == 0 :
print("flight got canceled...")
elif status == 1 :
print("flight is arrived...")
elif status == 2:
print("flight has departured already...")
else:
print("cannot confirm the flight status...,please check later") f = Flight("CA980")
f.flight_status()

航班查询

变成属性之后能否赋值呢?当然可以改, 不过需要通过@proerty.setter装饰器再装饰一下。

 class Flight(object):
def __init__(self,name):
self.flight_name = name def checking_status(self):
print("checking flight %s status " % self.flight_name)
return 1 @property
def flight_status(self):
status = self.checking_status()
if status == 0 :
print("flight got canceled...")
elif status == 1 :
print("flight is arrived...")
elif status == 2:
print("flight has departured already...")
else:
print("cannot confirm the flight status...,please check later") @flight_status.setter #修改
def flight_status(self,status):
status_dic = {
0 : "canceled",
1 :"arrived",
2 : "departured"
}
print("\033[31;1mHas changed the flight status to \033[0m",status_dic.get(status) ) @flight_status.deleter #删除
def flight_status(self):
print("status got removed...") f = Flight("CA980")
f.flight_status
f.flight_status = 2 #触发@flight_status.setter
del f.flight_status #触发@flight_status.deleter

航班查询(改进版)

4 类的特殊成员

  a、__doc__ 表示类的描述信息

 #Author:ZhangKanghui

 class Dog(object):
'''这个类是用来描述哈士奇的'''
def __init__(self):
pass print(Dog.__doc__)

__doc__

  b、__module__ 表示当前操作对象在那个模块

  c、__class__ 表示当前操作对象的类是什么

D07——C语言基础学PYTHON

 #Author:ZhangKanghui

 class A(object):
def __init__(self):
pass

lib

 #Author:ZhangKanghui

 from lib.empty import A
obj =A()
print(obj.__module__)
print(obj.__class__) class Dog(object):
def __init__(self,name):
self.name = name def __call__(self, *args, **kwargs):
print("here",args,kwargs) def __str__(self):
return ("<obj:%s>"%self.name) d =Dog("二哈")
#这样执行没问题,但是这样呢
#d() TypeError: 'Dog' object is not callable 你会发现d后面还能加括号怎么执行呢?
d(1,2,3,name='erha')
# Dog("二哈")(1,2,3,name='erha') # print(Dog.__dict__) #打印类的所有属性,不包括实例属性
# print(d.__dict__) #打印所有实例属性,不包括类属性
print(d)
'''有没有这些的区别呢?
def __str__(self):
return ("<obj:%s>" % self.name)
'''

index

 lib.empty
<class 'lib.empty.A'>
here (1, 2, 3) {'name': 'erha'}
<obj:二哈>

输出结果

  d、__init__ 构造方法,通过类创建对象时,自发触发执行。

  e、__del__ 析构方法,当对象在内存中被释放时,自发触发执行。

  f、__call__ 对象后面加括号触发执行

 class Foo:

     def __init__(self):
pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__
obj() # 执行 __call__

__call__

  g、__dict__ 查看类或对象中的所有成员

 #Author:ZhangKanghui

 class Province(object):
country = 'China' def __init__(self,name,count):
self.name = name
self.count = count def func(self,*args,**kwargs):
print(func)
#获取类的成员
print(Province.__dict__)
obj =Province("Henan",1000)
print(obj.__dict__)

__dict__

  h、__str__ 如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值  改变对象的字符串显示

 #Author:ZhangKanghui
class Dog(object):
def __init__(self,name):
self.name = name
self.__food = None
@property
def eat(self):
print("%s is eating %s" %(self.name,self.__food))
def __str__(self):
return "<obj:%s>"% self.name
d = Dog("erha")
print(d)
#如果直接进行实例化打印输出是个内存地址,此时在实例化钱定义__str__
#输出结果分别是:
#<__main__.Dog object at 0x038E42B0>
#<obj:erha>

__str__

  i、__getitem__  __setitem__  __delitem__  用于索引操作,如字典。以上分别表示获取、设置和删除数据。

 #Author:ZhangKanghui

 class Foo(object):
def __init__(self):
self.data ={} def __getitem__(self,key):
print("__getitem__", key)
return self.data.get(key)
def __setitem__(self, key, value):
print("__setitem__",key,value)
self.data[key] =value def __delitem__(self, key):
print("__delitem__", key) obj =Foo()
#这样实例化之后可以像字典一样给实例赋值
obj["name"] ="二哈"
print(obj["name"])
print(obj.data)
#这个时候的输出是一个字典
del obj["name"]
#输出结果__delitem__ name这个只是执行到这一步但是还没有执行

三合一

5 反射

主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。

通过字符串映射或修改程序运行时的状态、属性、方法, 有以下4个方法

 判断object中有没有一个name字符串对应的方法或属性

hasattr(obj,name)

def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass

getattr(obj,name)

def setattr(x, y, v): # real signature unknown; restored from __doc__
"""
Sets the named attribute on the given object to the specified value. setattr(x, 'y', v) is equivalent to ``x.y = v''
"""
pass

setattr(obj,str,val)

def delattr(x, y): # real signature unknown; restored from __doc__
"""
Deletes the named attribute from the given object. delattr(x, 'y') is equivalent to ``del x.y''
"""
pass

delattr(obj,str)

看完四个方法的定义之后就来看看实战怎么用?

 #Author:ZhangKanghui

 def bark(self):
print("%s is aoaoaoao...."% self.name) class Dog(object):
def __init__(self,name):
self.name = name def eat(self):
print("%s is eating..." %self.name) d =Dog("erha")
choice =input(">>:").strip()
'''
#d.choice #AttributeError: 'Dog' object has no attribute 'choice'
print(hasattr(d,choice))
#hasattr(obj,name_str) 判断一个对象obj里是否有对应的name_str字符串方法
print(getattr(d,choice))
#getattr(obj,name_str) 根据字符串去获取obj对象里对应方法的内存地址
getattr(d,choice)()
'''
#那么实际上我们会怎么写呢?
if hasattr(d,choice):
delattr(d,choice)
#func = getattr(d, choice)
#func("erha")
# print(func)
# setattr(d,choice,"hashiqi")
else:
'''
setattr(d,choice,bark) #d.choice = bark
#d.bark() TypeError: bark() missing 1 required positional argument: 'self'
d.talk(d) #在这里,看清楚是talk不是bark 但和d.bark(d)执行结果一样。这就是动态方法
#为什么talk和bark都是一样的呢?是因为输入的值其实就是choice
'''
#setattr(obj,y,v) is equivalent to x.y=v
#这是添加了一个动态方法,那么接下来我们给它加一个动态属性.先把上面注释了
setattr(d,choice,None)
v =getattr(d,choice)
print( v )
#方法在返回值时需要加括号,而属性不需要。如果此时我们传入的参数没有,比如age就返回None
#但是如果属性存在呢,比如name 那么他会报错,为什么?因为func是一的属性了不能加括号调用,那么把func()注释了呢
print(d.name) #delattr

反射1

 def delattr(x, y): # real signature unknown; restored from __doc__
"""
Deletes the named attribute from the given object. delattr(x, 'y') is equivalent to ``del x.y''
"""
pass
复制代码 复制代码
class BlackMedium:
feature='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr def sell_house(self):
print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
def rent_house(self):
print('%s 黑中介租房子啦,傻逼才租呢' %self.name) b1=BlackMedium('万成置地','回龙观天露园') #检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house')) #获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func() # getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊')) #设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.show_name(b1)) #删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错 print(b1.__dict__)

反射2

6 异常

 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的

常用异常

 ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError

更多异常

来看看实例:KeyError  IndexError  ValueError

 #Author:ZhangKanghui
'''
while True:
num1 = input('num1:')
num2 = input('num2:') try:
num1 = int(num1)
num2 = int(num2)
result = num1 + num2
except Exception as e:
print('出现异常,信息如下:')
print(e)
'''
#IndexError
dic = ["wupeiqi", 'alex']
try:
dic[10]
except IndexError as e:
print(e) #KeyError
dic = {'k1':'v1'}
try:
dic['k20']
except KeyError as e:
print(e) #ValueError
s1 = 'hello'
try:
int(s1)
except ValueError as e:
print(e) #万能异常Exception、
s1 = 'hello'
try:
int(s1)
except Exception as e:
print(e)

实例

 #Author:ZhangKanghui

 try:
#open(csv.xml)
a = 1
print(a)
except (IndexError,KeyError) as e:
print("Not Found 404",e)
except ValueError as e:
print("Not Found 101",e)
except Exception as e:
print("Unkown Error",e) else:
print("No Problem") finally:
print("不管有没有错,都会执行")

异常的其他结构

当然,我们也可以自定义异常,通过raise来触发。

 #Author:ZhangKanghui

 class MiracleException(Exception):
def __init__(self, msg):
self.message = msg
# def __str__(self):
# return self.message
#上面这两句注释了也不会出问题。
#主动出发异常
try:
raise MiracleException('你不能这么做')
except MiracleException as e:
print(e)

自定义异常

7 动态导入模块

 #Author:ZhangKanghui

 mod = __import__("lib.empty")       #lib
#mod = __import__("lib") #这样只能找到lib这一层 print(mod)
#<module 'lib' from 'C:\\Users\\miraacle\\PycharmProjects\\s\\day7\\lib\\__init__.py'>
print(mod.empty)
#<module 'lib.empty' from 'C:\\Users\\miraacle\\PycharmProjects\\s\\day7\\lib\\empty.py'>
print(mod.empty.A)
#<class 'lib.empty.A'> obj = mod.empty.A("erha")
print(obj.name)

form module import ...

 import importlib
mod = importlib.import_module("lib.empty") #这个是写到哪一层就是哪一层
print(mod)
print(mod.A)
print(mod.A("erha"))
print(mod.A("erha").name)

importlib

此外,还有一个拿来装比的  assert  断言

如果接下来的程序依赖于一个什么条件的情况下可以考虑用断言。这个必须正确才能继续往下进行。

 import importlib
mod = importlib.import_module("lib.empty") #这个是写到哪一层就是哪一层
obj = mod.A("erha")
assert type(obj.name) is str
print("我的断言屌不屌")

断言assert

8 小结

感觉自己走进了知识的海洋,然后溺水了!

要学的东西太多了。

慢慢来~厚积薄发

9 练习

其实,没有练习。

但是我还是放一个决策树算法的吧~

D07——C语言基础学PYTHON

 #Author:ZhangKanghui

 from sklearn.feature_extraction import DictVectorizer
import csv
from sklearn import tree
from sklearn import preprocessing
from sklearn.externals.six import StringIO # Read in the csv file and put features into list of dict and list of class label
allElectronicsData = open(r'/home/zhoumiao/MachineLearning/01decisiontree/AllElectronics.csv', 'rb')
reader = csv.reader(allElectronicsData)
headers = reader.next() print(headers) featureList = []
labelList = [] for row in reader:
labelList.append(row[len(row)-1])
rowDict = {}
for i in range(1, len(row)-1):
rowDict[headers[i]] = row[i]
featureList.append(rowDict) print(featureList) # Vetorize features
vec = DictVectorizer()
dummyX = vec.fit_transform(featureList) .toarray() print("dummyX: " + str(dummyX))
print(vec.get_feature_names()) print("labelList: " + str(labelList)) # vectorize class labels
lb = preprocessing.LabelBinarizer()
dummyY = lb.fit_transform(labelList)
print("dummyY: " + str(dummyY)) # Using decision tree for classification
# clf = tree.DecisionTreeClassifier()
clf = tree.DecisionTreeClassifier(criterion='entropy')
clf = clf.fit(dummyX, dummyY)
print("clf: " + str(clf)) # Visualize model
with open("allElectronicInformationGainOri.dot", 'w') as f:
f = tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f) oneRowX = dummyX[0, :]
print("oneRowX: " + str(oneRowX)) newRowX = oneRowX
newRowX[0] = 1
newRowX[2] = 0
print("newRowX: " + str(newRowX)) predictedY = clf.predict(newRowX)
print("predictedY: " + str(predictedY))

KNN实例应用

使用scikit-learn,需要安装sklearn模块才能用!

文档: http://scikit-learn.org/stable/modules/tree.html

我是尾巴~

这次是一个可视化工具:graphviz

安装Graphviz:http://www.graphviz.org/

转化dot文件至pdf可视化决策树:dot -Tpdf iris.dot -o outpu.pdf

虽不才~才要坚持