python学习心得与总结三

本周主要学习了类和面向对象的知识,学得容易,灵活运用却很难,还需要多加练习孰能生巧。

函数

参数、默认值、可变参数、关键字参数、命名关键字参数

可变参数:*args
关键字参数:**kwargs
返回值

嵌套定义
高阶函数、λ函数(匿名函数)、闭包、偏函数、柯里化

标识符
print(a)
作用域
L–E–G–B

类和对象

编程七大原则

单一职责原则

开闭原则

依赖原则

里氏替换原则

接口隔离原则(x)

合成聚合复用原则

扫描二维码关注公众号,回复: 1823277 查看本文章

迪米特法则(最少知识原则)

#关键字参数--字典--根据参数名来决定如何执行
#可变参数--输出的是元组
def say_hello(**kwargs):
    print(kwargs)
    for key in kwargs:
        print(key,'-->',kwargs[key])
    if 'name' in kwargs:
        print('你好,%s!' %kwargs['name'])
    elif 'age' in kwargs:
        age = kwargs['age']
        if age<= 16:
            print('你还是个小屁孩')
        else:
            print('你是个成年人')
    else:
        print('请提供个人信息')


def main():
    say_hello(name='熊彪',age='25')
    param = {'name':'王大锤','age':16,'tel':'15884550995'}
    #如果希望将一个字典作为关键字参数传入 需要在参数名前放两个*
    say_hello(**param)
    mylist = [1,2,3,7,8]
    #如果希望将一个列表或元组作为可变参数传入 需要在参数名前放一个*

#命名关键字参数

def foo (a,b,c,*,name,age):
    print(a+b+c)
    print(name,':',age)

foo(1,2,3,name = '熊彪',age = '25')


if __name__ == '__main__':
    main()
高阶函数,比如f(f(x))
高内聚 低耦合
通过向函数中传入函数,可以写出更通用的代码
calc函数中的第二个参数是另一个函数 它代表了一个二元运算
这样calc函数就不需要跟某一种特定的二元运算耦合在一起
所以calc函数变得通用性更强 可以由传入的第二个参数来决定到底是做什么运算
@property装饰器
slots魔法

(限定对象只能绑定某些属性)

继承和多态

子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)。

def my_sum(my_list):
    total = 0
    for val in my_list:
        total += val
    return total

def add(x,y):
    return x*y


def calc(my_list,op):
    total = my_list[0]
    for index in range(1,len(my_list)):
        total = op(total,my_list[index])
    return  total

def main():
    my_list = [1,3,5,2,7,8,9]
    print(calc(my_list,add))
    print(my_sum(my_list))


if __name__ == '__main__':
    main()


def record(fn):
    def wrapper(*args,**kwargs):
        print('准备执行%s函数' %fn.__name__)
        print(args)
        print(kwargs)
        #此行代码在执行被装饰的函数
        #在这行代码的前后我们可以附加其他的代码
        #这些代码可以让我们在执行函数时做一些额外的工作
        val = fn(*args,**kwargs)
        print('%s函数执行完成' %fn.__name__)
        print('返回了%d' %val)
        return  val
    return  wrapper
#通过装饰器修饰f函数 让f函数在执行过程中可以做更多额外的操作
@record
def f(n):
    if n==0 or n==1:
        return 1
    return n*f(n-1)

if __name__ == '__main__':
    print(f(5))
#奥特曼打小怪兽
from random import randint


class Ultraman(object):
    __slots__ = ('_name','_hp','_mp') #对对象属性做限制,不能加别的属性

    def __init__(self, name, hp, mp):
        self._name = name
        self._hp = hp
        self._mp = mp
#属性的访问器与修改器
    @property
    def name(self):
        return self._name

    @property
    def hp(self):
        return self._hp

    @hp.setter
    def hp(self, hp):
        self._hp = hp if hp >= 0 else 0

    def attack(self, monster):
        monster.hp -= randint(15, 25)

    def huge_attack(self, monster):
        if self.mp >= 50:
            self.mp -= 50
            injury = monster.hp * 3 // 4
            injury = injury if injury >= 50 else 50
            monster.hp -= injury
        else:
            self.attack(monster)

    def magic_attack(self, monsters):
        if self._mp >= 20:
            self._mp -= 20
            for monster in monsters:
                monster.hp -= randint(10, 15)

    def __str__(self):
        return '%s奥特曼\n' % self._name + \
               '生命值:%d\n' % self._hp + \
               '魔法值:%d\n' % self._mp


class Monster(object):
    __slots__ = ('_name','_hp')

    def __init__(self, name, hp):
        self._name = name
        self._hp = hp

    @property
    def name(self):
        return self._name

    @property
    def hp(self):
        return self._hp

    @hp.setter
    def hp(self, hp):
        self._hp = hp if hp >= 0 else 0

    def attack(self, ultraman):
        ultraman.hp -= randint(10, 20)

    def __str__(self):
        return '%s小怪兽\n' % self._name + \
               '生命值:%d\n' % self._hp



def main():
    u = Ultraman('熊彪', 1000, 200)
    m1 = Monster('陈晨1',250)
    m2 = Monster('陈晨2',500)
    m3 = Monster('陈晨3',800)
    ms = [m1,m2,m3]

    def die(m1,m2,m3):
        return False if m1.hp == 0 and m2.hp == 0 and m3.hp == 0 else True

    attack_round = 1
    while u.hp > 0 and die(m1,m2,m3):
        print('====第%d回合====' % attack_round)
        index = randint(0,2)
        u.attack(ms[index])
        u.magic_attack(ms)
        if ms[index].hp > 0:
            ms[index].attack(u)
        print(u)
        print(m1)
        print(m2)
        print(m3)
        # for n in range(3):
        #     print('小怪兽%s的生命值为%s' %(str(ms[n]._name),str(ms[n]._hp)))
        attack_round += 1
    if u.hp > 0:
        print('%s奥特曼胜利!' % u.name)
    else:
        print('小怪兽胜利!')


if __name__ == '__main__':
    main()
奥特曼打一群小怪兽
from random import randint, randrange
from abc import ABCMeta,abstractmethod

class Fighter(object,metaclass=ABCMeta):
    """战斗者"""

    # 通过__slots__魔法限定对象可以绑定的成员变量
    __slots__ = ('_name', '_hp')

    def __init__(self, name, hp):
        """
        初始化方法

        :param name: 名字
        :param hp: 生命值
        """
        self._name = name
        self._hp = hp

    @property
    def name(self):
        return self._name

    @property
    def hp(self):
        return self._hp

    @hp.setter
    def hp(self, hp):
        self._hp = hp if hp >= 0 else 0

    @abstractmethod
    def attack(self,other):
        pass

    @property
    def alive(self):
        return self._hp > 0


class Ultraman(Fighter):
    """奥特曼"""

    __slots__ = ('_name', '_hp', '_mp')

    def __init__(self, name, hp, mp):
        """
        初始化方法

        :param name: 名字
        :param hp: 生命值
        :param mp: 魔法值
        """
        super().__init__(name, hp)
        self._mp = mp

    def attack(self, monster):
        """
        攻击

        :param monster: 被攻击的小怪兽
        """
        monster.hp -= randint(15, 25)

    def huge_attack(self, monster):
        """
        究极必杀技

        :param monster: 被攻击的小怪兽

        :return: 使用成功返回True否则返回False
        """
        if self._mp >= 50:
            self._mp -= 50
            injury = monster.hp * 3 // 4
            injury = injury if injury >= 50 else 50
            monster.hp -= injury
            return True
        else:
            self.attack(monster)
            return False

    def magic_attack(self, monsters):
        """
        魔法攻击

        :param monsters: 被攻击的一群小怪兽

        :return: 使用魔法成功返回True否则返回False
        """
        if self._mp >= 20:
            self._mp -= 20
            for monster in monsters:
                if monster.alive>0:
                    monster.hp -= randint(10, 15)
            return True
        else:
            return False

    def resume(self):
        """恢复魔法值"""
        incr_point = randint(1, 10)
        self._mp += incr_point
        return incr_point

    def __str__(self):
        return '~~~%s奥特曼~~~\n' % self._name + \
               '生命值: %d\n' % self._hp + \
               '魔法值: %d\n' % self._mp


class Monster(Fighter):
    """小怪兽"""

    __slots__ = ('_name', '_hp')

    def attack(self, ultraman):
        """
        攻击

        :param ultraman: 被攻击的奥特曼
        """
        ultraman.hp -= randint(10, 20)

    def __str__(self):
        return '~~~%s小怪兽~~~\n' % self._name + \
               '生命值: %d\n' % self._hp


def is_any_alive(monsters):
    """判断有没有小怪兽是活着的"""
    for monster in monsters:
        if monster.alive > 0:
            return True
    return False


def select_alive_one(monsters):
    """选中一只活着的小怪兽"""
    monsters_len = len(monsters)
    while True:
        index = randrange(monsters_len)
        monster = monsters[index]
        if monster.alive > 0:
            return monster


def display_info(ultraman, monsters):
    """显示奥特曼和小怪兽的信息"""
    print(ultraman)
    for monster in monsters:
        print(monster, end='')


def main():
    u = Ultraman('骆昊', 1000, 120)
    m1 = Monster('舒小玲', 250)
    m2 = Monster('白元芳', 500)
    m3 = Monster('王大锤', 750)
    ms = [m1, m2, m3]
    fight_round = 1
    while u.alive and is_any_alive(ms):
        print('========第%02d回合========' % fight_round)
        m = select_alive_one(ms)  # 选中一只小怪兽
        skill = randint(1, 10)   # 通过随机数选择使用哪种技能
        if skill <= 6:  # 60%的概率使用普通攻击
            print('%s使用普通攻击打了%s.' % (u.name, m.name))
            u.attack(m)
            print('%s的魔法值恢复了%d点.' % (u.name, u.resume()))
        elif skill <= 9:  # 30%的概率使用魔法攻击(可能因魔法值不足而失败)
            if u.magic_attack(ms):
                print('%s使用了魔法攻击.' % u.name)
            else:
                print('%s使用魔法失败.' % u.name)
        else:  # 10%的概率使用究极必杀技(如果魔法值不足则使用普通攻击)
            if u.huge_attack(m):
                print('%s使用究极必杀技虐了%s.' % (u.name, m.name))
            else:
                print('%s使用普通攻击打了%s.' % (u.name, m.name))
                print('%s的魔法值恢复了%d点.' % (u.name, u.resume()))
        if m.alive > 0:  # 如果选中的小怪兽没有死就回击奥特曼
            print('%s回击了%s.' % (m.name, u.name))
            m.attack(u)
        display_info(u, ms)  # 每个回合结束后显示奥特曼和小怪兽的信息
        fight_round += 1
    print('\n========战斗结束!========\n')
    if u.alive > 0:
        print('%s奥特曼胜利!' % u.name)
    else:
        print('小怪兽胜利!')


if __name__ == '__main__':
    main()
约瑟夫环问题
def main():
    persons = [True]*30
    counter = 0
    index = 0
    number = 0
    while counter<15:
        if persons[index]:
            number += 1
            if number == 9:
                persons[index] = False
                counter +=1
                number = 0
        index +=1
        index %= 30
    for person in persons:
        print('基督徒' if person else '非基督徒',end = '')

if __name__ == '__main__':
    main()
线段上有两个点–has-a–关联关系
奥特曼打小怪兽—依赖关系
学生是人–继承关系
from  math import sqrt
class Point(object):

    def __init__(self,x=0,y=0):
        self._x = x
        self._y = y

    @property
    def x(self):
       return self._x
    @x.setter
    def x(self,x):
        self._x = x

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self,y):
        self._y=y


    def move_to(self,x,y):
        self._x = x
        self._y = y

    def move_by(self,dx,dy):
        self._x += dx
        self._y += dy

    def distance_to(self,other):
        dx = self._x-other.x
        dy = self._y-other.y
        return  sqrt(dx**2+dy**2)

    def __str__(self):
        return '(%s,%s)' %(str(self._x),str(self._y))


class Line(object):

    def __init__(self,start,end):
        self._start = start
        self._end = end


    @property
    def length(self):
        return self._start.distance_to(self._end)


def main():
    p1 = Point(3,5)
    print(p1)
    p2 = Point()
    print(p2)
    line = Line(p1,p2)
    print(line.length)

if __name__ == '__main__':
    main()

继承-从已经有的类创建新类的过程
提供继承信息的称为父类(超类/基类)
得到继承信息的称为子类(派生类/衍生类)
通过继承我们可以将子类中的重复代码抽取到父类中
子类通过继承并复用这些代码来减少重复代码的编写
将来如果要维护子类的公共代码只需要在父类中进行操作即可
方法重写(override)–覆盖/置换/覆写
子类在继承父类方法之后 对方法进行了重新实现
当我们给子类对象发送watch_av消息时执行的是子类重写过的方法

静态方法是指发给对象的包装器:@staticmethod
发给类的包装器是抽象类:@classmethod:def (对象)(cls,对象属性)

class Teacher(object):

    def __init__(self,name,age,title):
        self._name=name
        self._age=age
        self._title=title

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    @name.setter
    def name(self,name):
        self._name = name

    @age.setter
    def age(self,age):
        self._age=age

    @property
    def title(self):
        return self._title

    @title.setter
    def title(self,title):
        self._title=title

    def teach(self,course):
        print('%s%s正在讲%s.' %(self._name,self._title,course))





def main():

     t=Teacher('陈晨',25,'老师')
     t.teach('python程序设计')


if __name__ == '__main__':
    main()

python没有从语言层面支持抽象类的概念
我们可以通过abc模块来制造抽象类的效果
在定义类的时候通过指定metaclass=ABCMeta可以将类声明为抽象类
抽象类是不能创建对象的 抽象类存在的意义是专门拿给其他类继承
abc模块中还有一个包装器abstractmethod
通过这个包装器可以将方法包装为抽象方法 必须要求子类进行重写
有抽象方法就是抽象类

#员工工资结算
from abc import ABCMeta,abstractclassmethod

class Employee(object,metaclass=ABCMeta):
    """员工"""
    def __init__(self,name):
        """初始化方法"""
        self._name = name


    @property
    def name(self):
        return self._name

    @abstractclassmethod
    def get_salary(self):
        pass


class Manager(Employee):

    def get_salary(self):
        return 15000


class Programmer(Employee):
    def __init__(self,name):
        super().__init__(name)
        self._working_hour = 0

    @property
    def working_hour(self):
        return self._working_hour

    @working_hour.setter
    def working_hour(self,working_hour):
        self._working_hour = working_hour\
            if working_hour>0 else 0

    def get_salary(self):
        return 150*self._working_hour

class Salesman(Employee):
    def __init__(self,name,sales=0):
        super().__init__(name)
        self._sales = sales

    @property
    def sales(self):
        return self._sales

    @sales.setter
    def sales(self,sales):
        self._sales = sales if sales>0 else 0

    def get_salary(self):
        return 1200+self._sales*0.05

def main():
    emps = [Manager('刘备'),Programmer('诸葛亮'),Manager('曹操'),
            Salesman('荀彧'),Salesman('吕布'),Programmer('张辽'),Programmer('赵云')]

    for emp in emps:
        if isinstance(emp,Programmer):
            emp.working_hour = int(input('请输入%s本月工作时间:'% emp.name))
        elif isinstance(emp,Salesman):
            emp.sales = float(input('请输入%s本月销售额:'% emp.name))
            #同样是接收get_salary这个消息,但是不同的员工表现出了不同的行为
            #因为三个子类都重写了get_salary方法 所以这个方法会表现出多态行为
        print('%s本月工资为:¥%.2f元' %
              (emp.name,emp.get_salary()))


if __name__ == '__main__':
    main()
#创建银行账户类

class Account(object):
    def __init__(self,*,card_number,owner,balance=0):
        self._card_number=card_number
        self._owner=owner
        self._balance=balance

    @property
    def balance(self):
        return self._balance

    def deposit(self,money):
        if money>0:
            self._balance += money
            return True
        return False

    def withdraw(self,money):
        if 0<money<=self._balance:
            self._balance -= money
            return True
        return False

    def transfer(self,other,money):
        if self.withdraw(money):
            other.deposit(money)
            return True
        return False


def main():
    account = Account(card_number='1234567',owner='熊彪')
    print(account.balance)
    account.deposit(2000)
    account.withdraw(500) #Account.withdraw(account,500)
    print(account.balance)
    if account.withdraw(5000):
        print(account.balance)
    else:
        print('余额不足')
    account2 = Account(card_number='233443222',owner='陈晨',balance=120)
    if account.transfer(account2,800):
        print(account.balance)
        print(account2.balance)
    else:
        print('转账失败')



if __name__ == '__main__':
    main()
#创建分数类并且可以做加减乘除运算
from math import gcd

class Fraction(object):

    def __init__(self,num,den):
        if den == 0:
            raise ValueError('分母不能为0')
        self._den = den
        self._num = num
        self.normalize()
        self.simplify()

    @property
    def num(self):
        return self._num

    @property
    def den(self):
        return self._den

    def add(self,other):
        return Fraction(self._num*other.den+self._den*other.num,self._den*other.den)\
            .simplify().normalize()

    def sub(self,other):
        return Fraction(self._num*other.den-self._den*other.num,self._den*other.den)\
            .simplify().normalize()

    def mul(self,other):
        return Fraction(self._num*other.num,self._den*other.den).simplify().normalize()

    def div(self,other):
        return Fraction(self._num*other.den,self._den*other.num).simplify().normalize()
#运算符重写:
    def __add__(self, other):
        return self.add(other)

    def __sub__(self, other):
        return self.sub(other)

    def __mul__(self, other):
        return self.mul(other)

    def __truediv__(self, other):
        return self.div(other)

    def simplify(self):
        """化简"""
        if self._num != 0 and self._den != 1:
            factor = gcd(abs(self._num),abs(self._den))
            if factor > 1:
                self._num //= factor
                self._den //= factor
        return self


    def normalize(self):
        """正规化分数"""
        if self._den < 0:
            self._num = -self._num
            self._den = -self._den
        return self


    def __str__(self):
        if self._num == 0:
            return '0'
        elif self._den == 1:
            return str(self._num)
        else:
            return '%d/%d' %(self._num,self._den)


def main():
    f1 = Fraction(3,2)
    f2 = Fraction(5,4)
    print(f1+f2)
    print(f1-f2)
    print(f1*f2)
    print(f1/f2)



if __name__ == '__main__':
    main()
#创建扑克牌类


from  random import  randrange

class Card(object):
    """一张牌"""
    def __init__(self,suite,face):
        self._suite = suite
        self._face = face

    @property
    def face(self):
        return self._face

    @property
    def suite(self):
        return self._suite

    def __str__(self):
        if self._face == 1:
            face_str = 'A'
        elif self._face == 11:
            face_str = 'J'
        elif self._face == 12:
            face_str = 'Q'
        elif self._face == 13:
            face_str = 'K'
        else:
            face_str = str(self._face)
        return '%s%s' %(self._suite,face_str)



class Poker(object):
    """一副牌"""
    def __init__(self):
        self._cards = []
        self._current = 0
        for suite in  '♠♥♣♦':
            for face in range(1,14):
                card = Card(suite,face)
                self._cards.append(card)

    @property
    def cards(self):
        return self._cards

    def shuffle(self):
        """洗牌"""
        self._current = 0
        cards_len = len(self._cards)
        for index,card in enumerate(self._cards):
            pos = randrange(cards_len)
            self._cards[index],self._cards[pos] = \
                self._cards[pos],self._cards[index]

    @property
    def next(self):
        """发牌"""
        card = self._cards[self._current]
        self._current += 1
        return card

    @property
    def has_next(self):
        """还有没有牌"""
        return self._current<len(self._cards)

class Player(object):

    def __init__(self,name):
        self._name = name
        self._cards_on_hand = []
    @property
    def name(self):
        return self._name

    @property
    def cards_on_hand(self):
        return self._cards_on_hand

    def get(self,card):
        self._cards_on_hand.append(card)

    def arrange(self):
        self._cards_on_hand.sort(key=get_key)

def get_key(card):
    return card.face

def main():
    p = Poker()
    p.shuffle()
    players = [Player('东邪'),Player('西毒'),Player('南帝'),Player('北丐')]
    for _ in range(13):
        for player in players:
            player.get(p.next)
    for player in players:
        print(player.name + ':',end=' ')
        player.arrange()
        for card in player.cards_on_hand:
            print(card,end='')
        print()
if __name__ == '__main__':
    main()
用pygame做的五子棋游戏
import  pygame

EMPTY = 0
BLACK = 1
WHITE = 2
black_color = [0,0,0]
white_color = [255,255,255]
class RenjuBoard(object):

    def __init__(self):
        self._board = [[]]*15
        self.reset()

    def reset(self):
        for row in range(len(self._board)):
            self._board[row] = [EMPTY]*15

    def move(self,row,col,is_black):
        if self._board[row][col] == EMPTY:
            self._board[row][col] = BLACK if is_black else WHITE
            return True
        return False

    def draw(self,screen):
        for index in range(15):
            pygame.draw.line(screen, black_color, [20, 20 + 40 * index], [580, 20 + 40 * index], 1)
            pygame.draw.line(screen, black_color, [20 + 40 * index, 20], [20 + 40 * index, 580], 1)
        pygame.draw.rect(screen, black_color, [16, 16, 568, 568], 4)
        pygame.draw.circle(screen, black_color, [300, 300], 5, 0)
        pygame.draw.circle(screen, black_color, [140, 140], 5, 0)
        pygame.draw.circle(screen, black_color, [460, 460], 5, 0)
        pygame.draw.circle(screen, black_color, [460, 140], 5, 0)
        pygame.draw.circle(screen, black_color, [140, 460], 5, 0)
        for row in range(len(self._board)):
            for col in range(len(self._board[row])):
                if self._board[row][col] != EMPTY:
                    ccolor = black_color \
                        if self._board[row][col] == BLACK else white_color
                    pos = [40 * col + 20, 40 * row + 20]
                    pygame.draw.circle(screen, ccolor, pos, 20, 0)

def main():
    board = RenjuBoard()
    pygame.init()
    pygame.display.set_caption('五子棋')
    screen = pygame.display.set_mode([600,600])
    screen.fill([255,255,0])
    board.draw(screen)
    pygame.display.flip() #刷新窗口
    running = True
    is_black = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            # elif event.type == pygame.KEYUP:
            #     pass
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                x,y = event.pos
                row = round((y-20) / 40)
                col = round((x-20) / 40)
                if board.move(row,col,is_black):
                    is_black = not is_black
                    screen.fill([255,255,0])
                    board.draw(screen)
                    pygame.display.flip()
    pygame.quit()


if __name__ == '__main__':
    main()
用pygame做吃球游戏
import pygame
import time
from random import randint
class Ball(object):

    def __init__(self,center,color,radius,sx,sy):
        self._center = center
        self._color = color
        self._radius = radius
        self._sx = sx
        self._sy = sy
    @property
    def center(self):
        return  self._center
    @property
    def radius(self):
        return self._radius

    def move(self):
        x,y = self._center[0],self._center[1]
        x += self._sx
        y += self._sy
        self._center = (x,y)

        if x + self._radius >= 800 or x-self._radius <= 0:
            self._sx = -self._sx
        if y + self._radius >= 600 or y-self._radius <= 0:
            self._sy = -self._sy

    def eat(self,other):
        pass

    def draw(self,screen):
       pygame.draw.circle(screen, self._color,self._center,self._radius, 0)
       #0代表线条的宽度为0就是实心填充

def main():
    balls = []
    pygame.init()
    screen = pygame.display.set_mode([800, 600])
    pygame.display.set_caption('大球吃小球')
    clock = pygame.time.Clock()
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN and\
                event.button == 1:
                x,y = event.pos
                color = random_color()
                radius = randint(10,100)
                sx,sy = randint(-10,10),randint(-10,10)
                ball = Ball(event.pos,color,radius,sx,sy)
                balls.append(ball)
        refresh(screen,balls)
        clock.tick(24)
        for ball in balls:
            ball.move()


    pygame.quit()


def refresh(screen,balls):
    bg_color = (242, 242, 242)
    screen.fill(bg_color)
    for ball in balls:
        ball.draw(screen)
    pygame.display.flip()


def random_color():
    red = randint(0,255)
    green = randint(0,255)
    blue = randint(0,255)
    return red,green,blue

if __name__ == '__main__':
    main()
大球吃小球完整版

from random import randint
from math import sqrt

import pygame


class Ball(object):
    """球的类"""
    def __init__(self, center, color, radius, speed):
        """
        球的初始化方法

        :param center: 求的位置在哪
        :param color:  球的颜色
        :param radius:  球的半径
        :param speed:  球的速度
        """
        self._center = center
        self._color = color
        self._radius = radius
        self._speed = speed

    def move(self):
        """
        球的移动

        :return : None
        """
        x, y = self._center[0], self._center[1]  # 获取球当前的x, y坐标
        sx, sy = self._speed[0], self._speed[1]  # 获取当前球的速度
        if x + self._radius > 800:  # 如果球在右边框了
            x -= int(self._radius/4)+abs(sx)  # 大幅增加一个反向速度
            sx = -sx
        elif x - self._radius < 0:  # 如果球在左边框了
            x += int(self._radius/4)+abs(sx)
            sx = -sx
        elif y + self._radius > 600:  # 如果球在下边框了
            y -= int(self._radius/4)+abs(sy)
            sy = -sy
        elif y - self._radius < 0:  # 如果球在上边框了
            y += int(self._radius/4)+abs(sy)
            sy = -sy
        else:
            x, y = sx + x, sy + y  # 如果球在中间,正常的增减速度
        self._center = (x, y)  # 重置移动后的位置
        self._speed = sx, sy  # 速度重新赋值

    @property
    def center(self):
        """
        装饰器修饰后的get方法

        :return:  x,y的坐标元组
        """
        return self._center

    @property
    def radius(self):
        return self._radius

    def eat(self, other):
        """
        球吃的动作,主动,而非被动

        :param other:  被吃的球
        :return: 布尔值,是否被吃掉了
        """
        # 计算两球之间的距离
        distance = sqrt((self._center[0] - other.center[0]) ** 2 +
                        (self._center[1] - other.center[1]) ** 2)
        if distance < self._radius + other.radius and self._radius > other.radius:
            self._radius = int(sqrt(other.radius ** 2 + self._radius ** 2))  # 赋予吃了球后的新半径
            return True  # 吃球成功
        return False  # 吃球失败

    def draw(self, screen):
        center_pos = (self._center[0], self._center[1])
        pygame.draw.circle(screen, self._color, center_pos, self._radius)


def draw_ball():
    """
    画一个球

    :return:
    """
    balls = []
    pygame.init()
    display = pygame.display
    display.set_caption('大球吃小球')
    clock = pygame.time.Clock()
    screen = display.set_mode([800, 600])
    is_running = True
    while is_running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                is_running = False
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                color = random_color()
                radius = randint(10, 50)
                speed = [randint(-10, 10), randint(-10, 10)]
                ball = Ball(event.pos, color, radius, speed)
                balls.append(ball)
        clock.tick(30)
        for ball in balls:
            ball.move()
        # 通过双重for循环来判断,每个球是否能够被吃
        for index, ball in enumerate(balls):
            for j, other in enumerate(balls):
                if index != j:  # 不能自己吃自己
                    is_eat = ball.eat(other)  # 是否吃成功
                    if is_eat:
                        balls.pop(j)  # 成功后就将被吃的球拿出列表,达到消失的效果
        refresh(screen, balls)
    pygame.quit()


def refresh(screen, balls):
    """
    刷新游戏页面

    :param screen: 需要刷新的布局容器
    :param balls: 装球的列表
    :return:
    """
    bg_color = (255, 255, 255)
    screen.fill(bg_color)
    for ball in balls:
        ball.draw(screen)
    pygame.display.flip()


def random_color():
    """
    随机生成颜色

    :return: 返回随机后的元组
    """
    red = randint(0, 255)
    green = randint(0, 255)
    blue = randint(0, 255)
    return red, green, blue


def main():
    draw_ball()
    pass


if __name__ == '__main__':
    main()

贪吃蛇游戏

import pygame
from random import randint
from abc import ABCMeta, abstractmethod

BLACK_COLOR = (0, 0, 0)  # 全局常量,黑色
RED_COLOR = (255, 0, 0)  # 全局常量,红色
FOOD_COLOR = (230, 185, 185)  # 全局常量,食物的颜色
GREEN_COLOR = (0, 255, 0)  # 绿色

UP = 0  # 向上
RIGHT = 1  # 向右
DOWN = 2  # 向下
LEFT = 3  # 向左


class GameObject(object, metaclass=ABCMeta):
    """游戏物品抽象父类"""

    def __init__(self, pos=(0, 0), color=BLACK_COLOR):
        """初始化方法"""
        self._pos = pos  # 在界面中的位置
        self._color = color  # 在界面中的颜色

    @abstractmethod
    def draw(self, screen):
        """
        抽象方法,绘制对象

        :param screen: 在哪个图像表面层绘画
        :return: None
        """
        pass

    @property
    def pos(self):
        """
        装饰器修饰,直接获取对象在界面中的位置

        :return: 元组,(x,y)
        """
        return self._pos


class Wall(GameObject):
    """四周墙的类"""

    def __init__(self, pos, width, height, tick, color=BLACK_COLOR):
        """
        初始化、构造方法

        :param pos: 墙开始画的坐标点
        :param width: 墙的宽度
        :param height: 墙的高度
        :param tick: 墙的厚度
        :param color: 墙的颜色
        """
        super().__init__(pos, color)
        self._width = width
        self._height = height
        self._tick = tick

    @property
    def width(self):
        return self._width

    @property
    def height(self):
        return self._height

    def draw(self, screen):
        pygame.draw.rect(screen, self._color,
                         (self._pos[0], self._pos[1], self._width, self._height), self._tick)


class Food(GameObject):
    """食物类"""

    def __init__(self, pos, size=10, color=RED_COLOR):
        """
        初始化方法

        :param pos: 外切圆坐标
        :param color:
        :param size:
        """
        super().__init__(pos, color)
        self._is_hide = 0  # 是否隐藏的计数器,为了食物点不频繁的闪烁
        self._size = size  # 食物点的大小,直径

    def draw(self, screen):
        """
        绘制食物的方法

        :param screen: 在哪个表面绘制
        :return: None
        """
        # 如果不是5的倍数,就消失一次,减少Boolean值的频繁闪烁,数值越大闪烁越快
        if self._is_hide % 5 != 0:
            # 开始在界面进行绘制食物
            pygame.draw.circle(screen, self._color,
                               (self._pos[0] + self._size // 2, self._pos[1] + self._size // 2),
                               self._size // 2, 0)
        self._is_hide += 1  # 计数点自加


class SnakeNode(GameObject):
    """蛇的结点类"""

    def __init__(self, pos, size, color=GREEN_COLOR):
        """
        初始化构造方法

        :param pos: 结点的坐标
        :param size: 结点的大小
        :param color: 结点的颜色
        """
        super().__init__(pos, color)
        self._size = size

    def draw(self, screen):
        """
        绘制结点

        :param screen: 在哪个表面进行绘制
        :return: None
        """
        # 绘制内部绿色的结点
        pygame.draw.rect(screen, self._color,
                         (self._pos[0], self._pos[1], self._size, self._size), 0)
        # 绘制结点的外部边框
        pygame.draw.rect(screen, BLACK_COLOR,
                         (self._pos[0], self._pos[1], self._size, self._size), 1)

    @property
    def size(self):
        """
        装饰器,修饰get_size方法

        :return: 结点的大小
        """
        return self._size


class Snake(GameObject):
    """蛇的类"""

    def __init__(self):
        """
        初始化构造方法

        """
        super().__init__()
        self._snake_dir = LEFT  # 默认的蛇爬行的方向为左
        self._nodes = []  # 蛇的结点容器
        self._aline = True  # 蛇是否存活
        self._eat_food = False  # 是否吃到食物
        for index in range(5):  # 初始化5个结点在列表容器中
            node = SnakeNode((290 + index * 20, 250), 20)
            self._nodes.append(node)

    def is_in_nodes(self, x, y):
        """
        判断刷新出来的苹果是否在蛇的结点上

        :param x:  食物的x坐标
        :param y:  食物的y坐标
        :return: boolean 值,在为True,不在为False
        """
        for node in self._nodes:
            if node.pos[0] == x and node.pos[1] == y:
                return True
        return False

    @property
    def aline(self):
        """
        装饰器,获取对象属性

        :return: aline属性
        """
        return self._aline

    @property
    def snake_dir(self):
        """
        装饰器,获取蛇移动的方向

        :return: snake_dir 属性
        """
        return self._snake_dir

    @property
    def head(self):
        """
        装饰器,获取容器中的第一个结点

        :return: nodes[0] 第一个元素
        """
        return self._nodes[0]

    def change_dir(self, new_dir):
        """
        改变蛇前进的方向

        :param new_dir:  前进的新方向
        :return: None
        """
        # 如果方向和原来方向不同,而且相反,就可以改变,蛇的前进方向
        if new_dir != self._snake_dir and (self._snake_dir + new_dir) % 2 != 0:
            self._snake_dir = new_dir

    def draw(self, screen):
        """
        画出蛇

        :param screen: 在哪个表面画蛇
        :return: None
        """
        # 遍历结点,同时画出结点
        for node in self._nodes:
            node.draw(screen)

    def move(self):
        """
        蛇移动的方法

        :return: None
        """
        # if self._aline:
        head = self.head  # 获取蛇头
        snake_dir = self._snake_dir  # 获取蛇前进的方向
        # 获取蛇头想x,y坐标和头的大小
        x, y, size = head.pos[0], head.pos[1], head.size
        if snake_dir == UP:  # 向上移动
            y -= size  # y坐标减少
        elif snake_dir == RIGHT:  # 向右移动
            x += size  # x坐标增加
        elif snake_dir == DOWN:  # 向下移动
            y += size  # y坐标增加
        else:  # 向左移动
            x -= size  # x坐标减少
        new_head = SnakeNode((x, y), size)  # 新建一个结点对象
        self._nodes.insert(0, new_head)  # 添加到蛇头
        if self._eat_food:  # 如果吃到了食物
            self._eat_food = False  # 重设参数为没吃到,同时不移除最后的一个结点
        else:  # 没吃到食物
            self._nodes.pop()  # 移除最后的一个结点元素

    def collide(self, wall):
        """
        判断是否撞墙

        :param wall: 墙的对象
        :return: None
        """
        x, y = wall.pos  # 获取墙的坐标
        width = wall.width  # 获取墙的宽
        height = wall.height  # 获取墙的高
        node_one = self._nodes[0]  # 获取蛇头对象
        # 如果蛇头的x坐标小于了墙的最左边,或加上自身宽度大于了墙的初始位置加宽度,
        # 或蛇头的y坐标小于了墙最上面,或加上自身宽度大于了墙初始xy位置加高度
        if x > node_one.pos[0] or node_one.pos[0] + node_one.size > x + width \
                or y > node_one.pos[1] or node_one.pos[1] + node_one.size > y + height:
            self._aline = False  # 蛇撞到墙,死了
        else:
            self._aline = True  # 蛇没撞到墙,还或者

    def eat_food(self, food):
        """
        蛇吃食物的行为

        :param food: food对象
        :return: Boolean 是否吃到
        """
        head = self.head  # 获取蛇头结点
        # 如果蛇头的x,y坐标与食物的x,y坐标重合,那么就吃到了食物
        if head.pos[0] == food.pos[0] and head.pos[1] == food.pos[1]:
            self._eat_food = True  # 吃到食物的状态为True
            return True  # 返回True
        return False  # 没吃到食物返回False

    def eat_me(self):
        """
        吃自己判断

        :return: None
        """
        head = self.head  # 获取蛇头结点对象
        # 从蛇的第4个结点开始遍历,因为,蛇只能吃到自己的第四个结点
        for index in range(3, len(self._nodes)):
            # 如果蛇头坐标和蛇身坐标重合,就吃到了自己
            if head.pos[0] == self._nodes[index].pos[0] and \
                    head.pos[1] == self._nodes[index].pos[1]:
                self._aline = False  # 修改当前蛇的存活状态

    @property
    def snake_len(self):
        """
        获取蛇的结点长度

        :return: 蛇的长度
        """
        return len(self._nodes)


def main():
    """游戏主函数"""

    def refresh():
        """刷新游戏窗口"""
        screen.fill((242, 242, 242))
        snake.draw(screen)
        food.draw(screen)
        wall.draw(screen)
        pygame.display.flip()

    def handle_key_event(key_event):
        """游戏按键事件监听"""
        key = key_event.key  # 拿取到所按的按键的值
        if key == pygame.K_F2:  # 如果为F2则重新开始游戏
            reset_game()
        # 如果key为w,a,s,d则为方向控制
        elif key in (pygame.K_w, pygame.K_d, pygame.K_s, pygame.K_a):
            if snake.aline:  # 如果蛇还活着则进行操作
                if key == pygame.K_w:  # 按下了W
                    new_dir = UP  # 设置新的方向向上
                elif key == pygame.K_d:  # 按下了D
                    new_dir = RIGHT  # 设置新的方向向右
                elif key == pygame.K_s:  # 按下了S
                    new_dir = DOWN  # 设置新的方向向下
                else:  # 按下了A
                    new_dir = LEFT  # 设置新的方向向左
                snake.change_dir(new_dir)  # 调用蛇的方法,发送消息改变方向
        pygame.event.clear()  # 清除按键事件

    def reset_game():
        """重设游戏的食物和蛇的对象,游戏重开"""
        nonlocal food, snake, game_over  # 设置为嵌套值域,而非当前函数
        food = create_apple(snake)  # 创建新的食物对象
        snake = Snake()  # 创建新的蛇对象
        game_over = False  # 游戏继续

    scores = []  # 分数容器
    pygame.init()  # 初始化pygame
    wall = Wall((10, 10), 600, 600, 3)  # 创建墙的对象
    screen = pygame.display.set_mode([620, 620])  # 设置窗口大小
    screen.fill((242, 242, 242))  # 设置填充的背景
    pygame.display.set_caption('贪吃蛇')  # 设置窗口标题
    pygame.display.flip()  # 刷新界面
    clock = pygame.time.Clock()  # 设置时钟
    snake = Snake()  # 初始化一个蛇对象
    food = create_apple(snake)  # 初始化一个食物对象
    reset_game()  # 重开游戏,刷新界面
    is_running = True  # 游戏运行状态
    game_over = False  # 游戏当前回合状态
    while is_running:
        for event in pygame.event.get():  # 获取事件
            if event.type == pygame.QUIT:  # 判断事件类型是否为退出
                is_running = False
            elif event.type == pygame.KEYDOWN:
                handle_key_event(event)  # 传递按钮点击事件
        if not game_over:  # 本回合是否继续
            if snake.aline:  # 当前蛇是否还存活
                refresh()  # 刷新游戏窗口
                snake.move()  # 蛇开始移动
                snake.collide(wall)  # 判断蛇是否撞墙
                snake.eat_me()  # 判断蛇是否吃到自己
                if snake.eat_food(food):  # 判断蛇是否吃到食物
                    food = create_apple(snake)  # 吃到食物,创建一个新的食物对象
            else:  # 本回合结束
                game_over = True  # 设置本回合结束
                scores.append(snake.snake_len - 5)  # 将分数添加到容器中
                show_info(screen, scores)  # 显示分数
        clock.tick(5)  # 帧数
    pygame.quit()  # 销毁pygame
    pass


def show_info(screen, scores):
    """
    在界面中绘制分数的函数

    :param screen:  绘制的表面
    :param scores:  绘制的分数列表
    :return:  None
    """
    scores.sort(reverse=True)  # 对分数进行排序
    my_font = pygame.font.SysFont('宋体', 60)  # 设置字体格式
    game_over = my_font.render('GAME OVER', False, [0, 0, 0])  # 字体的文本和颜色
    screen.blit(game_over, (180, 260))  # 开始绘制的坐标
    list_len = len(scores) if len(scores) < 5 else 5  # 获取分数容器的大小,最多展示前五
    for index in range(list_len):  # 遍历欠前五的分数
        my_font = pygame.font.SysFont('宋体', 40)  # 设置字体
        # 绘制的文字内容和分数
        score = my_font.render('Number ' + str(index + 1) + ':' + str(scores[index]), False, [255, 0, 0])
        screen.blit(score, (200, 300 + index * 40))  # 绘制的位置
    pygame.display.flip()  # 刷新界面


def create_apple(snake):
    """
    创建苹果在蛇的身体之外

    :param snake:  蛇的对象
    :return: 在蛇身之外的Food坐标
    """
    row = randint(0, 29)  # 随机行号
    col = randint(0, 29)  # 随机列号
    x, y = 10 + 20 * col, 10 + 20 * row  # 换算为对应的坐标点
    if not snake.is_in_nodes(x, y):  # 如果不在蛇身上
        return Food((10 + 20 * col, 10 + 20 * row), 20)  # 返回一个食物对象
    else:
        create_apple(snake)  # 递归调用函数直到有返回值


if __name__ == '__main__':
    main()

文件的读写

异常机制-处理程序在运行过程中出现意外状况的手段,把可能出意外的代码保护起来
因为不是所有的问题都能够在写程序调试程序的时候就能发现
打开文件–>判断大小–>分配内存–>读取文件–>关闭文件
import time
def main():
    try:#保护下面的代码防止程序崩溃
        with open('./abc/zhou5.2.py','r',encoding='utf-8') as fs:
            # content = fs.read()
            # for line in fs:
            #     print(line,end='')
            #     time.sleep(1)
            # print(content)
            mylist = fs.readlines()
            print(mylist)
            #fs.close()
    except (FileNotFoundError ,IOError):
        print('指定的文件无法打开')
    print('程序执行结束')



if __name__ == '__main__':
    main()

import json
def main():

    studet = {'name':'熊彪','age':25,'grade':65}
    try:

        with open('data.json','r',encoding='utf-8') as fs:

            yourdict = json.load(fs)
            print(type(yourdict))
            print((yourdict))
        with open('data.json','w',encoding='utf-8') as fs:
            json.dump(studet,fs)
    except IOError as e:
        print((e))

if __name__ == '__main__':
    main()

def main():
    try:
        with open('./tu/mv/1.jpg','rb') as fs1:
            data = fs1.read()
            print(data)

        with open('./abc/cd.jpg', 'wb') as fs2:
           fs2.write(data)



    except (FileNotFoundError, IOError):
        print('指定的文件无法打开')
    print('程序执行结束')

if __name__ == '__main__':
    main()


from math import sqrt


def is_prime(n):
    assert n>0

    for factor in range(2,int(sqrt(n))+1):
        if n%factor == 0:
            return False
    return True if n!=1 else False

def main():
    filenames = ['a.txt','b.txt','c.txt']
    fs_list = []
    try:
        #把可能出状况(在执行时有风险)的代码放到try代码块保护执行
        for filename in filenames:
            fs_list.append(open(filename,'w',encoding='utf-8')) #把文件流装进新的容器
        for number in range(1,10000):
            if is_prime(number):
                if number<100:
                    fs_list[0].write(str(number) + '\n')

                elif number<1000:
                    fs_list[1].write(str(number) + '\n')

                else:
                    fs_list[2].write(str(number)+'\n')

#except可以写多个分别用于处理不同的异常状况
    except IOError:
        #如果try中出现了状况就通过except来捕获错误(异常)进行对应的处理
        print('读写文件错误!')
    else:
        pass
        #如果没有出状况那么可以把无风险的代码放到else中执行
    finally:
        #此处是最好的释放外部资源的位置因为这里的代码总是会执行
        #所以此处最适合做释放外部资源的操作
        for fs in fs_list:
            fs.close()
    print('操作完成!')



if __name__ == '__main__':
    main()

# URL - Uniform Resource Locator
#天行数据找美女图片
import requests
import json


def main():
    # request / response
    resp = requests.get('http://api.tianapi.com/meinv/?key=81a5d68102a2826cbc8220c325d1a440&num=10')
    mydict = json.loads(resp.text)
    for tempdict in mydict['newslist']:
        pic_url = tempdict['picUrl']
        resp = requests.get(pic_url)
        filename = pic_url[pic_url.rfind('/') + 1:]
        try:
            with open(filename, 'wb') as fs:
                fs.write(resp.content)
        except IOError as e:
            print(e)


if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/xiongbiao_xiongqi/article/details/79594079