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

python学习之面向对象学习

2017-06-12 19:11 309 查看
一、什么事面向对象,以及面向对象的优点?
面向过程优缺点:
我们知道面向过程是流水线式的编程,过程就是解决问题的步骤,把大的问题化解成小的模块
面向过程优点: 极大的降低了程序的复杂度
面向过程缺点: 牵一发而动全身, 所以完成一个模块很少改动,否则改动的地方比较多

面向对象优缺点:
面向对象编程的核心是对象,由属性和函数构成
面向对象优点: 解决程序的扩展性,对某个类的修改能反映到整个体系中

类的语法结构:
class 类名:
类体

例子:
class People:
language = 'Chinese'
def func(self):    #self把对象自身传进去
pass

p1 = People
p2 = People
print(p1.language)
print(p2.language)
p1.language = 'english'
print(p1.language)    #输出english
print(p2.language)    #输出english

注: 所有对象共用类的属性,所以p2也输出english

初始化类__init__
例子:
class Garen:
camp='Demacia'
def __init__(self,nickname, aggressivity=58,life_value=456):
self.nickname = nickname
self.aggressivity = aggressivity
self.life_value = life_value

def attack(self,enemy):
enemy.life_value -= self.aggressivity
hero = Garen('garen', 100, 600)    #加括号初始化类对象
print(isinstance(hero, Garen))    #isinstance判断hero是否是类Garen的实例,是则返回True,否则返回False
print(Garen.__name__)   #类的名称
print(Garen.__doc__)    #类的文档字符串
print(Garen.__base__)   #类的第一个父类
print(Garen.__bases__)  #类的所有父类构成的元组
print(Garen.__dict__)   #类的字典属性
print(Garen.__module__) #类定义所在的模块
print(Garen.__class__)  #实例对应的类

将函数绑定到对象上叫做对象的方法,并且会把自身传递给函数作为第一个参数

对象的交互:
class Riven:
camp = 'Noxus'
def __init__(self, nickname, aggressivity=54,life_value=300):
self.nickname = nickname
self.aggressivity = aggressivity
self.life_value = life_value

def attack(self,enemy):
enemy.life_value -= self.aggressivity

r1 = Riven('瑞问问')

print(hero.life_value)
r1.attack(hero)
print(hero.life_value)
print(id(r1.attack))    #id打印函数位置
print(id(Riven.attack))

类有两种属性:数据属性和函数属性,数据属性共享给所有对象。
方法是绑定到所有对象上的,并且对象会传递给函数
创建对象就是创建了一个命名空间,对象会先找自己的命名空间,再找类的命名空间

二、继承
继承是一种创建新类的方式
继承的好处,减少代码冗余,
子类覆盖父类的方法叫做派生

例子:
class ParentClass1:
pass

class ParentClass2:
pass

class SubClass1(ParentClass1):
pass
class SubClass2(ParentClass1,ParentClass2):
pass

print(SubClass1.__bases__)    #打印父类
print(SubClass2.__bases__)    #打印父类

继承关系如图:



F->A->E-B->D->C




F->D->B-E->C->H->A
派生类
例子:
class Animal:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex

def eat(self):
print('eating')

def talk(self):
print('%s 正在叫' %self.name)

class People(Animal):
def __init__(self,name,age,sex,education):
Animal.__init__(self,name,age,sex)
self.education = education

def talk(self):
Animal.talk(self)
print('%s say hello' %self.name)

class Pig(Animal):
pass

class Dog(Animal):
pass

peo1 = People('hyh',20,'male','小学毕业')
pig1 = Pig('zhangsan', 16, 'male')
dog1 = Dog('lisi', 16, 'female')
peo1.talk()
pig1.talk()
dog1.talk()
print(isinstance(peo1, People))    #判断peo1是否是People类,返回True或False
print(isinstance(pig1, Pig))        #继承反映的什么是什么的关系
print(isinstance(dog1, Dog))
通过__dict__获取属性
class Sub:
def __init__(self):
self.bar = 123
def bar(self):
print('Sub.bar')

s = Sub()
print(s.__dict__)
print(s.__dict__['bar'])

组合: 在一个类中,以另外一个类的对象作为数据属性,称为类的组合,组合反映的是什么有什么的关系,
例子:
class People:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
class Date:
def __init__(self,year,mon,day):
self.year = year
self.mon = mon
self.day = day

def tell(self):
print('%s-%s-%s' %(self.year,self.mon,self.day))

class Teacher(People):
def __init__(self,name,age,sex,salary,year,mon,day):
self.name = name
self.age = age
self.sex = sex
self.salary = salary
self.birth = Date(year,mon,day)

class Student(People):
def __init__(self,name,age,sex,year,mon,day):
self.name=name
self.age=age
self.sex=sex
self.birth=Date(year,mon,day)

t=Teacher('egon',18,'male',3000,1995,12,31)
t.birth.tell()

定义类模拟接口
例子:
class File:
def read(self):
raise TypeError('类型错误')

def write(self):
raise TypeError('类型错误')

class Txt(File):
def read(self):
print('文本数据的读取方法')

def write(self):
print('文本数据的读取方法')

class Sata(File):
def read(self):
print('硬盘数据的读取方法')

def wirte(self):
print('硬盘数据的读取方法')

class Process(File):
def read(self):
print('进程数据的读取方法')

def write(self):
print('进程数据的读取方法')

p = Process()
p.read()
t = Txt()
d = Sata()
print(isinstance(p, Process))
print(isinstance(t, Txt))
print(isinstance(d, Sata))

注: File类定义功能函数,Txt,Sata,Process分别定义实现函数的方法

调用父类用super方法
例子:
class Foo1:
def test(self):
print("from foo1.test")

class Foo2:
def test(self):
print('from foo2.test')

class Bar(Foo1,Foo2):
def test(self):
super().test()
print('Bar')
b = Bar()
b.test()
三、封装
封装:主要为了保护数据的隐私,而把数据隐藏起来,只能通过接口去访问
类中通过__双下划线来隐藏数据属性和函数属性,含有__x的属性都会变成_类名__x的形式:
Foo:
__x = __test():   ()
(Foo.)
封装实例:
class People:
__country = 'China'

def __init__(self,name,age,sex):
self.__name = name
#self._People__name = name
self.__age = age
self.__sex = sex

def tell_info(self):
print('人的名字是:%s, 人的年龄是: %s, 人的性别是: %s' %(self.__name, self.__age, self.__sex))
p = People('alex', 29, 'male')
print(p.__dict__)
p.tell_info()

注: 封装只在定义时检查语法
p.__x = 1
print(p.__x)    #打印1

修改属性接口
class People:
def __init__(self,name,age):
self.__name = name
self.__age = age

def tell_info(self):
print('人的名字是: %s, 人的年龄是: %s' %(self.__name, self.__age))

def set_info(self,x, y):
if not isinstance(x, str):
raise TypeError('名字必须是字符串')
if not isinstance(y, int):
raise TypeError('年龄必须是整数')

self.__name = x
self.__age = y

p = People('alex', 20)
p.tell_info()
p.set_info('hyh', 18)
p.tell_info()

四、特性
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
例子:
class People:
def __init__(self,name,weight,height):
self.name=name
self.weight=weight
self.height=height
@property
def bmi(self):
return self.weight / (self.height**2)

p1=People('egon',75,1.85)
print(p1.bmi)

将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是
执行了一个函数然后计算出来的,这种特性的使用方式遵循统一访问原则

五、绑定方法与非绑定方法
类中定义的函数分成两大类:

  一:绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入):

    1. 绑定到类的方法:用classmethod装饰器装饰的方法。

为类量身定制

类.boud_method(),自动将类当作第一个参数传入

(其实对象也可调用,但仍将类当作第一个参数传入)

    2. 绑定到对象的方法:没有被任何装饰器装饰的方法。

为对象量身定制

对象.boud_method(),自动将对象当作第一个参数传入

(属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)

  二:非绑定方法:用staticmethod装饰器装饰的方法

     1. 不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已

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

例子:
import hashlib
import time
class MySQL:
def __init__(self,host,port):
self.id=self.create_id()
self.host=host
self.port=port
@staticmethod
def create_id(): #就是一个普通工具
m=hashlib.md5(str(time.clock()).encode('utf-8'))
return m.hexdigest()
print(MySQL.create_id) #<function MySQL.create_id at 0x0000000001E6B9D8> #查看结果为普通函数
conn=MySQL('127.0.0.1',3306)
print(conn.create_id) #<function MySQL.create_id at 0x00000000026FB9D8> #查看结果为普通函数

classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个
参数(即便是对象来调用也会将类当作第一个参数传入),python为我们内置了函数classmethod来把类中的函数定义成类方法

例子:
settings.py文件内容
HOST='127.0.0.1'
PORT=3306

import settings
import hashlib
import time
class MySQL:
def __init__(self,host,port):
self.host=host
self.port=port

@classmethod
def from_conf(cls):
print(cls)
return cls(settings.HOST,settings.PORT)
print(MySQL.from_conf) #<bound method MySQL.from_conf of <class '__main__.MySQL'>>
conn=MySQL.from_conf()print(conn.host,conn.port)
conn.from_conf() #对象也可以调用,但是默认传的第一个参数仍然是类
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  学习 python 对象学习