十一、Python之面向对象

1.概念

1)面向过程与面向对象
面向过程,核心是过程二字,过程即解决问题的步骤,就是先干什么再干什么
基于该思想写程序好比在设计一条流水线,是一种机械式的思维方式
优点:复杂的过程流程化,进而简单化
缺点:扩展性差

面向对象,核心是对象二字,对象是特征与技能的结合体
基于该思想写程序就好比在创造世界,世界是由一个个对象组成,是一种’上帝式' 的思维方式
优点: 可扩展性强
缺点: 编程复杂高,容易出现过度设计

2) 类
对象是特征与技能的结合体,类就是一系列对象相似的特征与技能的结合体
在现实世界中:一定是先有一个个具体存在的对象,后总结出的类
在程序中: 一定保证先定义类,后产生对象

3) 实例化
调用类的过程又称为实例化

2.类(Class)程序实例

1)定义一个Student类

class Student:
school = 'oldboy'

def learn(self):
print('is learning')

def choose_course(self):
print('choose course')
print('======run')

函数只有在调用时才能运行,而类体代码在类定义时就能执行

print(Student.dict)

查看属性

print(Student.school) #类的数据属性
print(Student.learn) #类的函数属性

增加属性

Student.country = 'china'
print(Student.country)

修改属性

Student.school = 'Oldboy'
print(Student.school)

删除属性

del Student.country
#print(Student.country) #删除后就访问不到,则会报错

Student.learn('AAAA') #必须传值,才能执行

2)定义一个Teacher类

class Teacher:
school = 'oldboy'
count = 0
def init(self,name,sex,age,level,salary):
self.name = name
self.sex = sex
self.age = age
self.level = level
self.salary = salary
Teacher.count+=1
def teach(self):
print('%s is teaching' %self.name)

t1 = Teacher('张三','male',18,10,3000)
t2 = Teacher('李四','male',38,9,30000)
t3 = Teacher('王五','male',29,9,30000)

通过调用实例下的name打印老师名字

print(t1.name) #张三
print(t2.name) #李四
print(t3.name) #王五

调用任何一个实例,count都是老师的总个数

print(t1.count) #3
print(t2.count) #3
print(t3.count) #3

3.类的继承与派生

在Python2中类分为2种:
1.经典类
2.新式类:指的是继承object类的类,以及该类的子类

在Python3中只有新式类,默认会继承object类的类,以及该类的子类
=================================================
Python2 Python3
class Parten1(object) 等同于 class Partent1()
=================================================

class Parent2:
pass

class Sub1(Parent1):
pass

class Sub2(Parent1,Parent2):
pass

Sbu1 继承了Parent1

print(Sub1.bases)

Sub2 继承了Paren1 Parent2

print(Sub2.bases)

默认会有继承 object

print(Parent1.bases) #(<class 'object'>,)
print(Parent2.bases) #(<class 'object'>,)

4.多态与多态性

多态:同一种事物的多种形态,对于动物来说,动物都能叫,但是可能内容不同,即呈现出来的状态不同

import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractclassmethod
def speak(self):
pass

class Pig(Animal):
def speak(self):
print('哼哼')

class Dog(Animal):
def speak(self):
print('汪汪')

dog=Dog()
pig=Pig()

dog、pig都是动物,只要是动物肯定有talk方法,于是我们可以不用考虑它们具体是什么类型,而直接使用

dog.talk()
pig.talk()

更进一步,我们可以定义一个统一的接口来使用

def func(obj):
obj.talk()

5.封装

封装:变量前面加 __
对于隐藏的变量在定义阶段就会变形
如果在定义之后,再增加新变量,即使加__也不会隐藏
对于隐藏变量在类的定义中是可以直接调用的,而在实例化之后就不能直接调用了,变量前面必须加上 _类名

example1=========================================================================

class Foo:
__N = 1
def init(self,x,y):
self.__x = x
self.__y = y
def __f1(self):
print('f1')
def f2(self): #类的内部是可以直接调用__x,__y的
print(self.__x,self.__y)

print(Foo.dict)
obj = Foo(1,2)
print(obj._Foo__x) #1
obj.f2() #1 2

END=============================================================================

example2=========================================================================

class Foo:
def __f1(self):
print('Foo.f1')
def f2(self):
print('Foo.f2')
self.__f1()

class Bar(Foo):
def __f1(self):
print('Bar.f1')
obj = Bar()
obj._Bar__f1() #Bar.f1
obj.f2() #Foo.f2 Foo.f1
#END============================================================================

example3========================================================================

class Foo:
def init(self,name,age):
self.__name = name
self.__age = age

def get_info(self):
print('姓名:<%s> 年龄:<%s>' %(self.__name,self.__age))

def set_info(self,name,age):
if type(name) is not str:
raise TypeError ('name must be str') #如果不满足条件,主动抛出一个异常
if type(age) is not int:
raise TypeError ('age must be int')
self.__name = name
self.__age = age

sub1 = Foo('egg',18)
sub1.get_info()
sub1.set_info('egon',123) #__name __age 是封装了的变量,无法直接访问,这里通过一个接口(set_info)对这2个变量进行修改
sub1.get_info()

6.反射

class Foo:
def init(self,name):
self.name = name
def f1(self):
pass

obj = Foo('egon')
print(obj.dict)

hascttr 判断是否有某个属性

print(hasattr(obj,'name')) # obj.name

getattr 判断有没有该属性,有拿出来

if hasattr(obj,'f1'):
f=getattr(obj,'f1')

setattr 设置新属性

setattr('obj','x',1)

7.绑定方法与非绑定方法

1)定义(转载 http://www.cnblogs.com/linhaifeng/articles/7341177.html )

一:绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入):
1. 绑定到类的方法:用classmethod装饰器装饰的方法
为类量身定制
类.boud_method(),自动将类当作第一个参数传入
(其实对象也可调用,但仍将类当作第一个参数传入)
2. 绑定到对象的方法:没有被任何装饰器装饰的方法
为对象量身定制
对象.boud_method(),自动将对象当作第一个参数传入
(属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)

二:非绑定方法:用staticmethod装饰器装饰的方法
不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已
注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而 staticmethod装饰的方法,不管谁来调用,都没有自动传值一说

2)实例代码

import settings
import hashlib
import time
class MySQL:
def __init(self,host,port):
self.host = host
self.port = port
@classmethod #绑定给类,若不加该装饰器默认绑定给对象
def from_conf(cls):
return(settings.HOST,settings.PORT)
@staticmethod #取消绑定
def create_id(n):
m=hashlib.md5()
m.update(str(time.clock()+n).encode('utf-8'))
return m.hexdigest()

conn = MySQL.from_conf()

posted @ 2018-01-27 21:17  丢失固执  阅读(192)  评论(0)    收藏  举报