类属性与类方法

面向对象三大特征:
1.封装:根据职责将属性和方法封装到一个抽象的类中
2.继承:实现代码的重用。相同的代码不需要重复的编写
3.多态:(以封装和继承为前提),不同的子类对象调用相同的方法,产生不同的执行结果
class Dog(object):
    def __init__(self,name):
        self.name=name
    def game(self):
        print '%s 蹦蹦跳跳的玩 '%self.name
class Xiaotiandog(Dog):
    #父类方法不能满足子类的方法,重写game方法
    def game(self):
        #在使用继承时,子类拥有父类的所有属性和方法
        print '%s飞上天上  '%self.name
class Persion(object):
    def __init__(self,name):
        self.name=name
    def game_with_dog(self,dog):
        print '%s与%s快乐的玩'%(self.name,dog.name)
        #让dog玩耍
        dog.game()
#lucky=Dog('幸运')
#创建一个狗对象
lucky=Xiaotiandog('小小')
#创建一个lili对象(lili是一个人)
lili=Persion('lili')
#让lili调用和狗玩的方法(把之前创建的狗对象传递进去)
lili.game_with_dog(lucky)


案例小结;
Persion类中只需要让狗对象调用game方法(这是子类的父类中封装的方法)而不关心具体是什么狗
game方法是在Dog父类中定义的
在程序执行时,传入不同的狗对象的实参,就会产生不同的执行效果

一切皆对象  类是一个特殊的对象---类对象
在程序运行的时候,类对象(创建实例对象的模版)在内存中只有1份,通过他可以创建出很多个对象实例
除了封装实例的属性和方法外,类对象还可以拥有自己的属性和方法 类属性 类方法
类属性:就是给类对象定义的属性,通常用来记录与这个类相关的特征,类属性不会用于记录具体的对象特征
例子:定义一个工具类,每个工具都有自己的名字
     需要知道使用这个类,创建了多少个工具对象
class Tool(object):
    #使用赋值语句定义类属性,记录所有工具的数量
    count=0
    def __init__(self,name):
        self.name=name
        #让类属性加1
        Tool.count+=1
#创建工具对象
tool1=Tool('镰刀')
tool2=Tool('符头')
#输出工具对象的总数
#使用 类名.属性名  来获取
print Tool.count  #通过类名. 的方式可以直接访问类的属性

类属性就是针对类对象定义的,使用赋值语句在class关键字下可以定义类属性
类属性用于记录这个类相关的特性
类方法就是针对类对象定义的方法在类方法内部就可以直接访问类属性或者调用其他类方法
class  Toy(object):
    #使用赋值语句定义类属性,记录所有玩具的数量
    count=0
    @classmethod
    def show_toy_count(cls):
        #cls.count 在类方法内部,访问当前的类属性
        print '玩具对象的数量%d'%cls.count
    def __init__(self,name):
        self.name=name
        #让类属性加1
        Toy.count+=1
#创建玩具对象
toy1=Toy('乐高')
toy2=Toy('积木')
#调用类方法
Toy.show_toy_count()

静态方法
    在开发的时候,如果需要在类中封装一个方法,这个方法即不需要访问实例属性或者调用实例方法
    也不需要访问类属性和类方法,这个时候,我们就可以把这个方法封装成一个静态方法
class Cat(object):
    #不访问实例属性/类属性
    @staticmethod
    def call():
        print '喵喵'
#通过 类名. 调用静态方法,不需要创建对象,直接就可以使用
Cat.call()


设计 类的结构
术语--实例
1.使用面向对象开发,第一步是设计类
2.使用 类名() 创建对象,创建对象的动作有两步
    1.在内存中为对象分配空间
    2.调用初始化方法__init___ 为对象初始化
3.对象创建后,内存中就有了一个对象的实实在在的存在--实例

因此:
1.创建出来的对象叫做类的实例
2.创建对象的动作叫做实例化
3.对象的属性叫做实例属性
4.对象调用的方法叫做实例方法

在程序执行时:
1.对象各自拥有自己的实例属性
2.调用对象的方法,可以通过self
    访问自己的属性
    调用自己的方法
结论:
1.每一个对象都有自己独立的内存空间,保存各自不同的属性
2.多个对象的方法,在内存中之有一份,在调用方法时,需要把对象的引用传递到方法内部

 


设计一个Game类
属性:
定义一个属性top_score记录游戏的历史最高分
定义一个属性player_game记录当前游戏玩家的玩家姓名
方法:
show_help 显示游戏帮助信息
show_top_score显示历史最高分
start_game开始当前玩家的游戏

class Game(object):
     #历史最高分
    top_score=0
    #实例属性在初始化方法内部定义
    def __init__(self,name):
        Game.top_score+=1
        self.name=name
    @classmethod
    def show_history_score(cls):
        print '历史最高分为%d'%cls.top_score
    @staticmethod
    def show_help():
        print '游戏帮助信息如下'
    def start_game(self):
        print '%s开始玩家游戏'%self.name
#1.查看帮助信息
Game.show_help()
#创建游戏对象,开始游戏
king=Game('king')
print king.name
king.start_game()
#3.查看历史最高分
Game.show_history_score()


案例小结:
1.实例方法----方法内部需要访问实例属性  实例方法内部可以使用 类名. 访问类属性
2.类方法:方法内部只需要访问类属性
3.静态方法:方法内部,不需要访问实例属性和类属性
提问:
如果方法内部,及需要访问实例属性,又需要访问类属性,应该定义什么方法?
答案:
应该定义实例方法:
因为,类只有一个,在实例方法内部可以使用类名. 访问类属性


#设计模式是前人的总结和经验的提炼,通常被人们广流传的设计模式都是针对某一特定的功能
单例设计模式
单例:让类创建的对象,在系统中有唯一的实例
创建对象的时候:
1.为对象分配空间:__new__()
创建对象的时候,python解释器首先会调用__new__方法为对象分配空间
__new__是一个由object基类提供的内置的静态方法,主要有两个作用:
    在内存中为对象分配空间
    返回对象的引用
2.对象初始化: __init__()
python解释器获得对象的引用后,将引用的第一个参数,传递给__init__方法
class MusciPlayer(object):
    def __new__(cls,*args,**kwargs):
        #第一个参数cls:哪一个类调用就传递哪一个类
        #第二个参数*args:是一个多值元组参数
        #第三个参数**kwargs:是一个多值字典参数
        #1.创建对象时,new方法会被自动调用
        print '创建对象,分配空间' #重写了父类的方法
        #2.为对象分配空间
        #__new__方法是一个静态方法,在调用的时候,第一个参数是cls
        instance=object.__new__(cls)
        #返回对象的引用
        return instance
    def __init__(self):
        print '初始化播放器'
#创建播放器对象
player1=MusciPlayer()
print player1          ##两个对象的内存地址是不一样的
player2=MusciPlayer()
print player2

重写__new__方法的代码非常固定:
    继承自父类方法
    返回父类方法调用__new__方法的结果
重写__new__方法一定要return object.__new__(cls)
否则python 的解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法
python中的单例:
单例:让类创建的对象,在系统中只有唯一的一个实例
    1.定义一个类属性,初始值为None,用于记录单例对象的引用(因为当一个类定义完成运行程序的时候,内存中有这个类创建的对象么?并没有,我们需要调用创建对象的方法,内存中才会有第一个对象)
    2.重写__new__方法
    3.如果类属性is  none,调用父类方法分配空间,并在类属性中记录结果
    4.返回类属性中记录的对象的引用
class MusicPlayer(object):
    #记录第一个被创建对象的应用
    instance=None
    def __new__(cls,*args,**kwargs):
         #判断类属性是否为空(如果是空对象,说明第一个对象还没被创建)
        if cls.instance  is  None:
            #调用父类的方法,为第一个对象分配空间
            cls.instance=object.__new__(cls)
        #返回类属性保存对象引用
        return cls.instance
#创建多个对象
player1=MusicPlayer()
print player1
player2=MusicPlayer()   ##两个对象的内存地址是一样的
print player2

只执行一次初始化工作
在每次使用类名()创建对象时,python解释器都会自动调用两个方法
    __new__ 分配空间
    __init__ 对象初始化
但是在上一小结中__new__方法改造之后,每次都会得到第一次被创建对象的引用
但是初始化方法还会被再次调用
需求:让初始化只执行一次
解决方法:
1.定义一个类属性init_flag标记是否执行过初始化动作,初始值为False
2.在__init__方法中,判断init_flag,如果为False就执行初始化动作
3.然后将init_flag设置为true
4.这样,再次自动调用__init__方法时,初始化动作就不会再次被执行了
class MusicPlayer(object):
    #记录第一个被创建对象的应用
    instance=None
    init_flag=False
    def __new__(cls,*args,**kwargs):
        #判断类属性是否为空(如果是空对象,说明第一个对象还没被创建)
        if cls.instance  is  None:
        #调用父类的方法,为第一个对象分配空间
            cls.instance=object.__new__(cls)
        #返回类属性保存对象引用
        return cls.instance
    def __init__(self):
        #判断是否执行过初始化方法
        if MusicPlayer.init_flag:
            return
        #如果没有执行,执行初始化动作
        else:
            print '初始化播放器'
        #修改类属性的标记
        MusicPlayer.init_flag=True
#创建多个对象
player1=MusicPlayer()
print player1
player2=MusicPlayer()   ##都执行一次
print player2

异常:
程序在运行的时候,如果python解释器遇到一个错误,会停止程序的执行,并且提示一些错误的信息,这就是异常
我们在程序开发的时候,很难将所有的特殊情况都处理,通过异常捕获可以针对突发事件做集中处理,从而保证程序的健壮性和稳定性
在程序开发中,如果对某些代码的执行不能确定(程序语法完全正确)
可以增加try来捕获异常
try:
    尝试执行的代码
except:
    出现错误的处理
except 错误类型1:
    针对错误类型1,对应的代码处理
except 错误类型2:
    针对错误类型2,对应的代码处理
"""    
try:
    #不能确定正确执行的代码
    num=int(raw_input('请输入一个整数:'))
except:
    print '请输入正确的整数'
print '*'*35

需求:提示用户输入一个整数
     使用8除以用户输入的整数并输出
try:
    #提示用户输入一个整数
    num=int(raw_input('请输入一个整数:'))
    #使用8/整数并且输出
    result=8/num
    print result
except ZeroDivisionError:
    print '0不能做除数'
except ValueError:
    print '输入的值不是数字'
print '*'*35


try:
    num=int(raw_input('请输入一个整数:'))
    result=8/num
    print result
# except ZeroDivisionError:
#     print '0不能做除数'
except ValueError:
    print '输入的值不是数字'
#没有预先判断到的错误,但是如果出现,我们也不希望程序停止
except Exception as result:
    print '未知的错误%s'%result
finally:
    #无论是否异常,都会执行的代码
    print '无论是否异常,都会执行的代码'
print '*'*35

异常的传递
def demo1():
    return int(raw_input('输入整数'))
def  demo2():
    return demo1()
#函数的错误:一级一级的去找,最终会将异常传递到主程序里面
#print demo2()
try:
    print demo2()
except Exception as result:
    print '未知错误%s'%result


需求:提示用户输入密码,如果长度小于8,就抛出异常
def input_passwd():
    #提示用户输入密码
    pwd=raw_input('请输入密码')
    #判断密码的长度》=8,就返回用户的密码
    if len(pwd)>=8:
        return pwd
   #如果《8,就主动抛出异常
    print '主动抛出异常'
    #创建异常对象
    ex=Exception('密码长度不够')
    #主动抛出异常
    raise ex
#注意:只抛出异常而不捕获异常,代码会出错
try:
    print input_passwd()
except Exception as result:
    print result

断言:可以理解为提前预言,让人更好的知道错误的原因
def func(num,div):
    assert (div !=0),'div不能为0'
    return num/div
print func(10,0)

r:只能读,不能写   读取的文件不存在会报错
r+:可读可写,读取的文件不存在会报错
w:只能写,不能读,会清空覆盖文件内容 如果文件不存在,会新建文件
w+:可读可写,会清空覆盖文件内容 如果文件不存在,会新建文件
a:只能写,不能读  文件不存在,新建文件不报错  文件存在 不会清空文件内容
a+:可读可写,文件不存在,新建文件不报错  文件存在 不会清空文件内容
文件操作3部曲:打开  操作 关闭
f=open('wb','w+')
content=f.read()
f.write('bad')
print content
f.close()


练习:
创建文件data.txt,文件共10000行,每行存放一个1~100之间的整数
import random
i=0
f=open('data.txt','w+')
while i<=10:
    content=f.read()
    a=random.randint(1,1000)
    f.write( '%d\n'%a)
    print content
f.close

#文件指针
#文件指针标记从那个位置开始读取数据
#第一次打开文件时,通常文件指针会指向文件的开始位置
#当执行了read方法后,文件指针会移动到读取内容的末尾
file=open('passwd')
text=file.read()
print text
print type(text)
print len(text)
print '#######'
#移动文件指针到文件开头
file.seek(0)
text=file.read()
print len(text)
file.close()

#正确读取大文件
file=open('passwd')
#为什么要设定为无限循环,因为我们不知道循环的条件,我们不知道文件到底有多少行
while True:
    text=file.readline()
    #判断是否读取到了内容
    #如果文件指针到文件到文件的最后一行,那么就读取不到内容了
    if not text:
        break
    #每读取一行的末尾已经有一个'\n'
    print text
file.close()

#文件的copy
#打开一个已经有的文件,读取完整的内容,并写入到另一个文件中去
#源文件以只读的方式打开
file_read=open('passwd')
#目标文件以只写的方式打开
file_write=open('passwd_copy','w')
#从源文件中读取内容
text=file_read.read()
#将读取到的内容写道目标文件
file_write.write(text)
#关闭文件
file_read.close()
file_write.close()

##编写二进制文件
f1=open('good.jpg',mode='rb')
content=f1.read()
f1.close()
f2=open('happy.png',mode='wb')
f2.write(content)
f2.close()

##不用关闭文件的套路
with open('passwd')as f:
    lines=f.readline()
    print lines
for line in lines:
    print line


练习:
生成一个大文件ips.txt,要求1200行,每行随机为172.25.254.0/24段的ip
读取ips.txt文件统计这个文件中ip出现频率排前10的ip;
import random
def create_ips_file(filename):
    ips=['172.25.254.'+str(i) for i in range(1,255)]
    with open(filename,'a+')as f:
        for count in range(1200):
            f.write(random.sample(ips,1)[0]+'\n')   
def sorted_by_ip(filename,count=10):
    ips_dict=dict()
    with open(filename)as f:
        for ip in f:
            if ip in ips_dict:
                ips_dict[ip]+=1
            else:
                ips_dict[ip]=1
     sorted_ip=sorted(ips_dict.items(),
                     key=lambda x:x[1],reverse=True)[:count]
    return sorted_ip
#print create_ips_file('ips.txt')
print sorted_by_ip('ips.txt')


           

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值