面向对象

本篇文章的主要内容为内置函数、匿名函数、递归函数、面向对象基础知识、面向对象的组合、面向对象的继承以及面向对象的多态。

1.内置函数

'''
整体说明:
01 研究python的内置函数。
02 以下内置函数都是常用的,并且比较重要的。
'''

# 01 locals:当前作用域的所有的变量  **
# 0101 当作用域为全局变量,输出全局的变量。
name = '太白'
age = 25


def func1():
    a1 = 'Ws'
    b1 = {'name': '马玉刚'}


func1()
print(locals())   # 打印出所有的全局变量,以字典的形式输出,其中name = '太白'

# 0102 当前作用域为局部变量,输出局部的变量。
name = '太白'
age = 25


def func1():
    a1 = 'Ws'
    b1 = {'name': '马玉刚'}
    print(locals())  # 打印函数func1的局部变量,以字典的形式输出,其中name = '马玉刚'

func1()

# 02 globals: 永远获取的是全局作用所有的变量等。  **

name = '太白'
age = 25


def func1():
    a1 = 'Ws'
    b1 = {'name': '二狗'}
    print(globals())   # 打印出所有的全局变量,以字典的形式输出,其中name = '太白'


func1()
print(globals())   # 打印出所有的全局变量,以字典的形式输出,其中name = '太白'

# 03 eval:执行字符串类型的代码,并返回最终结果。(慎用:由于采用用户输入或者接口对接的时候如果不校验直接执行的话, 则比较容易被黑客作为攻击的入口)
eval('2 + 2')  # 4

n = 81
eval("n + 4")  # 85

eval('print(666)')  # 666

# 04  exec:执行字符串类型的代码 (慎用:原因同上)
s = '''
for i in [1,2,3]:
    print(i)
'''
exec(s)

#04 print  输出
''' 源码分析
def print(self, *args, sep=' ', end='\n', file=None): # known special case of print
    """
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    file:  默认是输出到屏幕,如果设置为文件句柄,输出到文件
    sep:   打印多个值之间的分隔符,默认为空格
    end:   每一次打印的结尾,默认为换行符
    flush: 立即把内容输出到流文件,不作缓存
    """
'''

print(111, 222, 333, sep='*')  # 111*222*333

print(111, end='')
print(222)  # 两行的结果 111222

f = open('log', 'w', encoding='utf-8')
print('写入文件', file = f, flush=True)

# 05 hash:获取一个对象的哈希值(可哈希对象:int,str,Bool,tuple)
print(hash(12322))
print(hash('123'))
print(hash('arg'))
print(hash('alex'))
print(hash(True))
print(hash(False))
print(hash((1, 2, 3)))


'''
执行结果:
12322
-2996001552409009098
-4637515981888139739
2311495795356652852
1
0
2528502973977326415
'''

06 open:函数用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写。

07 __import__ :模块相关,函数用于动态加载类和函数

# 08 help:用于查看函数或模块用途的详细说明。
print(help(str))

# 09 callable  判断对象是否可调用,如果返回True,object仍然可能调用失败;但如果返回False,调用对象ojbect绝对不会成功。  **
a1 = 'barry'
def func1():
    print(666)
print(callable(a1))   # False

print(callable(func1))  # True

# 10 dir :查看内置属性,函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。
# 如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。

dir
print(dir('alex'))

# 11 进制转换(3)(1)bin:将十进制转换为二进制并且返回。(2)oct:将十进制转换为八进制字符串并返回。(3)hex:将十进制转换为十六进制字符串并返回。


print(bin(10), type(bin(10)))  # 0b1010 <class 'str'>
print(oct(10), type(oct(10)))  # 0o12 <class 'str'>
print(hex(10), type(hex(10)))  # 0xa <class 'str'>

# 12 数学运算共7个:abs,divmod,round,pow,sum,min,max
# abs:函数返回数字的绝对值。
# divmod:计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)。分页会用到,返回商数和余数。**
print(divmod(7, 3))  # (2,1)
# round:保留浮点数的小数位数,默认保留整数。
# pow:求x**y次幂。
# sum:对可迭代对象进行求和计算(可设置初始值)。
print(sum([i for i in range(10)]))  # 默认初始值是0,输出结果为45.
print(sum([i for i in range(10)], 100))  # 设置默认初始值为100,输出结果为145。
# min:返回可迭代对象的最小值(可加key,key为函数名,通过函数的规则,返回最小值)。 ***
# 常规式的输出最小值
print(min(1, 2, 3, 4, 5))
print(min([1, 2, 3, 4, 5]))
print(min([('alex', 3), ('太白', 1), ('wS', 2)]))  # 按照unicode编码去比较大小,首先比较每个元素中的第一个,之后逐个比较,直至比较出大小来即可。
# 加key的输出最小值(key为函数名)
# min 默认将可迭代对象中的每个元素依次传入函数中,按照函数的返回值去取最小元素。
l1 = [('alex', 3), ('太白', 1), ('wS', 2)]


def func(x):
    return x[1]  # min将可迭代对象中的每个元素依次传入函数中,并且按照返回值取最小元素。该返回值是将列表中每个元素的第二个作为返回值返回。


print(min(l1, key=func))  # ('太白', 1)
#
# max:返回可迭代对象的最大值(可加key,key为函数名,通过函数的规则,返回最大值)。 ***
# max的使用和min一样。

# 13 reversed:将一个序列翻转,返回一个新的翻转的迭代器。 ***
l1 = [2, 3, 4, 1]
l2 = reversed(l1)
print(list(l2))

# 14 format 字符串可以提供的参数,指定对齐方式,<是左对齐, >是右对齐,^是居中对齐。
print(format('test', '<20'))  # 以20个字符为长度,进行左对齐
print(format('test', '>20'))
print(format('test', '^20'))

# 15 bytes:用于不同编码之间的转化。 **
s1 = '太白'
# unicode ---> utf-8 bytes
b1 = s1.encode('utf-8')
print(b1)
# utf-8 bytes ---> unicode
s2 = b1.decode('utf-8')
print(s2)

s1 = '太白'
# unicode ---> utf-8 bytes
b1 = bytes(s1, encoding='utf-8')
print(b1)

# 16 ord:输入字符找该字符编码的位置
print(ord(''))  # 20013
print(ord('a'))   # 97,

# 17 chr:输入位置数字找出其对应的字符
print(chr(97))   # a
print(chr(20013))  #

#18 ascii:是ascii码中的返回该值,不是就返回/u...
print(ascii('a'))   # 'a'
print(ascii(''))  # '\u4e2d'

# 19 repr:返回一个对象的string形式(原形毕露)。
s1 = "alex"
l3 = '[1,2,3]'
print(s1)  # alex
print(l3)  # [1,2,3]
print(repr(s1))  # 'alex'
print(repr(l3))  # '[1,2,3]'

# 20 %r-也会使字符串原型毕露,用处是引用别人说的话时,如果需要保留单引号的时候,就需要用%r。
s1 = '我叫%s, 我是%r' % ('alex', 'sb')
print(s1)

# 21 sorted:对所有可迭代的对象进行排序操作。
l1 = [1, 2, 7, 6, 5, 4]
l2 = sorted(l1)
print(l2)  # [1, 2, 4, 5, 6, 7]

l1 = [('alex', 3), ('太白', 1), ('wS', 2), ('wS', 4)]


def func(x):
    return x[1]


new_l = sorted(l1, key=func, reverse=True)  # sorted:将可迭代对象中的每个元素依次传入函数中,并且将每个元素中的第二个返回进行排序,同时进行倒序输出。
print(new_l)  # [('wS', 4), ('alex', 3), ('wS', 2), ('太白', 1)]

# 22 # enumerate::枚举,返回一个枚举对象。  ***
l1 = ['太白%s' % i for i in range(10)]

for index, i in enumerate(l1, 10):  # 设置默认索引数字从10开始,i从0开始进行循环
    print(index, i)

# 23 all:可迭代对象中,全都是True才是True **
print(all([1, 2, True, 100]))  # True

# 24 any:可迭代对象中,有一个True 就是True **
print(any(['', 0]))  # False

'''
# 24  zip 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同。   ***
'''
l1 = [1, 2, 3, 6, 7, 8, 9]
l2 = ['a', 'b', 'c', 5]
l3 = ('*', '**', (1, 2, 3))

print(zip(l1, l2, l3))  # 生成一个可迭代对象
for i in zip(l1, l2, l3):
    print(i)

'''
<zip object at 0x0000000001E95608>
(1, 'a', '*')
(2, 'b', '**')
(3, 'c', (1, 2, 3))
'''

# 25  filter 返回是迭代器  类比成列表推导式:筛选模式  ***
l1 = [i for i in range(100) if i % 2 == 0]
print(l1)


l2 = [1, 2, 3, 4, 5, 6]


def func(x):
    return x % 2 == 0  # 筛选条件


obj1 = filter(func, l2)
print(list(obj1))  # [2, 4, 6],切记一定要加上list,否则只是一个迭代器。

# 26 map: 返回一个迭代器  类比成列表推导式:循环模式  ***
l1 = [1, 2, 3, 4, 5, 6]


def func(x):
    return x ** 2  # 返回值


print(list(map(func, l1)))

2.匿名函数

'''
整体说明;
01 一句话函数,一行代码实现的函数
02 格式:函数名 = lambda 输入:返回值
'''

# 01 计算两个数字的和
func1 = lambda x, y: x + y
print(func1(2, 3))

# 02 三个数的运算

func2 = lambda x, y, z: (x + y - z) * 2
print(func2(2, 5, 6))

# 03 匿名函数与内置函数结合使用
l1 = [1, 2, 3, 4, 5, 6]
obj1 = filter(lambda x: x % 2 == 0, l1)
print(obj1)  # <filter object at 0x00000000021AE2E8>,直接打印是一个迭代器
print(list(obj1))  # 打印一个列表[2, 4, 6]

# 04 输出字典种value最大的key
l = [3, 2, 100, 999, 213, 1111, 31121, 333]
dic = {'k1': 10, 'k2': 100, 'k3': 30}

ret = max(dic, key=lambda x: dic[x])
print(ret)

3.递归函数

'''
整体说明:
01 自己用自己。
02 默认的递归次数:999(998)
03 递归函数一定要有返回值(返回值基本上都是函数自己调用自己)

'''

# 01 用递归函数实现斐波那契数列
# 1 1 2 3 5 8 13 21 .....
# 1 2 3 4 5 6 7  8 .....



def fib(n):
    if (n == 1 or n == 2):
        return 1
    else:
        return fib(n - 1) + fib(n - 2)


print(fib(20))

'''
推到过程:
fib(3) = fib(2) + fib(1)
fib(4) = fib(3) + fib(2)
。。。。
fib(n) = fib(n - 1) + fib(n - 2)
'''

4.面向对象基础知识

'''
整体说明:
01 相同功能的函数进行分类。
02 面向对象的特点:
    (1)它是将某些相关的功能(函数)封装到一起。
    (2) 站在上帝的角度,创建一个公共模板,然后通过模板创造不同的对象。
03 类:具有相同属性和技能的一类事物。
04 对象:类的具体表现。
05 类的分析方法:
    (1)结构分析:类一般分为两个部分,即静态变量(静态属性/静态字段),动态方法(函数)。
    (2)思想分析:创建一个类的公共模板,通过创建个体对象可以享有公共方法。
06 类的调用:类中的静态属性一般通过类名去调用或者改变;类中的动态方法一般通过对象去执行。
07 类名的应用
    (1)类名调用类中的静态属性。
        a)方法一:__dict__  只能查询(不能增删改) 类中所有的静态属性,动态方法。
        b)方法二: 万能的点 .  可以查,可以改,可增,可删。
    (2)类名执行类中的动态方法。(一般不建议用类名执行,除非是特殊方法:类方法,静态方法)
08 实例化对象:类名+()就是一个实例化对象的过程,具体步骤如下:
    (1)实例化对象在内存中产生一个对象空间(内存地址)。
    (2)自动执行 __init__方法并且将对象空间传给了self参数。***
    (3)在 __init__方法中,给对象空间封装一些静态属性。
09 对象的应用
    (1)对象调用类的静态属性
    (2)万能的点: .可以调用类中的静态属性。
    (3)对象执行类中动态方法:
10  self 约定俗成 self,类中的方法的第一个参数要设定为self,在对象调用方法时,会自动将对象空间传给self。
11 __init__方法:作用是给对象封装属性。
'''

# 01 定义一个类person
class Person:
    mind = '有思想'
    animal = '高级动物'
    language = '文字语言'  # 静态属性,静态变量 静态字段

    def work(self):  # 函数 方法,动态方法,动态属性。
        print('人类都会工作')

    def eat(self):
        print('人类都需要吃饭')

# 02 类名的应用
# 0201 类名调用类中静态属性

class Person:
    mind = '有思想'
    animal = '高级动物'
    language = '文字语言'  # 静态属性,静态变量 静态字段

    def work(self):  # 函数 方法,动态方法,动态属性。
        print('人类都会工作')

    def eat(self):
        print('人类都需要吃饭')
# 方法一:__dict__  只能查询(不能增删改) 类中所有的静态属性,动态方法。
print(Person.__dict__)
print(Person.__dict__['mind'])
Person.__dict__['mind'] = '无思想的' # 不能这样修改,因为方法一只能查询,不能增删改
print(Person.__dict__)

# 方法二: 万能的点 .  可以查,可以改,可增,可删。
print(Person.animal)
Person.animal = '低级动物'  # 修改类中的静态属性
Person.name = '有姓名'  # 增加类中的静态属性
print(Person.animal)
del Person.animal
# print(Person.animal)   # 报错,因为上一步已经删除类Person中animal静态属性,所以会报错。
print(Person.__dict__)

# 0202 类名执行类中的动态方法 (一般不建议用类名执行,除非是特殊方法:类方法,静态方法)
Person.work('alex')   #  不建议用类名执行动态方法。

# 03 __init__:作用是给对象封装属性。
# 以下是定义游戏角色的类Game_Role
class Game_Role:
    a1 = '英雄联盟'
    name = '太白'
    def __init__(self, name, sex, ad, hp):  # __init__方法,特殊方法: 给对象封装属性
        # print(self)
        # print(666)
        ''' 以下给对象封装的属性'''
        self.name = name
        self.sex = sex
        self.ad = ad
        self.hp = hp


    def fight(self,*args, **kwargs):
        pass

gailun = Game_Role('盖伦', 'man', 30, 500)  # 进行对象的实例化,即gailun = Game_Role,默认执行__init__函数,给对象封装属性。
print(gailun.name)  # 通过万能的点,由实例化的对象进行静态属性的展示。

# 04 对象的应用。
# 0401 对象调用类中的静态属性;通过万能的点:.可以调用类中的静态属性。
print(gailun.name)  # 通过万能的点,由实例化的对象进行静态属性的展示。
# 0402 对象执行类中的动态方法。
class Game_Role:
    a1 = '英雄联盟'
    name = '太白'
    def __init__(self, name, sex, ad, hp):  # __init__方法,特殊方法: 给对象封装属性
        # print(self)
        # print(666)
        ''' 以下给对象封装的属性'''
        self.name = name
        self.sex = sex
        self.ad = ad
        self.hp = hp


    def fight(self,*args, **kwargs):
        pass

    def work(self):
        self.hobby = '大刀' # 增加对象的属性
        print(self.__dict__)


gailun = Game_Role('盖伦', 'man', 30, 500)  # 进行对象的实例化,即gailun = Game_Role,默认执行__init__函数,给对象封装属性。
gailun.work()
print(gailun.hobby)  # 大刀

# 0403 对象查看自己的空间属性
# 查看全部:__dict__
# 查看某个对象自己的静态属性:万能的点,实现增删改查。
print(gailun.name)
print(gailun.sex)
gailun.name = 'GAIlun'
gailun.hobby = '大刀'
print(gailun.hobby)
print(gailun.__dict__)

5.面向对象组合

'''
整体说明:
01 对象与对象之间是不能相互访问的, 彼此独立。
02 对象可以访问类中的所有内容,但是类名不能访问对象中的内容。
03 组合的作用:让类的对象和另一个类的对象发生关联,从而可以互相访问。(通过一个对象的属性是另一个类的对象来实现)
'''

'''
程序说明:
01 定义了两个类,即角色类和武器类,其中角色类中的ad代表攻击力,hp代表血量。
02 需求是盖伦使用大宝剑攻击沟通一次(只计算工具本身对狗头血量的消耗,暂时忽略盖伦本身的攻击力)
'''
class Game_Role:
    area = '召唤师峡谷'
    
    def __init__(self, name, sex, ad, hp):
        self.name = name
        self.sex = sex
        self.ad = ad  # 攻击力
        self.hp = hp  # 血量
    
    def fight(self, role1):
        role1.hp = role1.hp - self.ad
        print('%s 攻击 %s, %s还剩余%s' % (self.name, role1.name, role1.name, role1.hp))
        # print(self, role1)
    
    def equit_weapon(self, wea): # 组合: 对象中的属性是另一个类的对象,将Weapon类的对象sword作为Game_roles类的实例化对象P1的封装的属性。
        self.wea = wea


class Weapon:
    def __init__(self, name, ad):
        self.name = name
        self.ad = ad
    
    def wea_attack(self, role1, role2):
        role2.hp = role2.hp - self.ad
        print('%s 利用 %s 攻击 %s, %s还剩余%s' % (role1.name, self.name, role2.name, role2.name, role2.hp))


p1 = Game_Role('盖伦', 'man', 30, 500)
p2 = Game_Role('狗头', '', 50, 250)
# p3 = Game_Role('诺克', 'man', 50, 350)
# p1.fight(p2)

sword = Weapon('大宝剑', 40)
# print(sword)
# sword.wea_attack(p1, p2)
p1.equit_weapon(sword)  # 此方法就是给p1对象封装一个属性,属性值是sword对象
# print(p1.wea.name)
# # print(p1.wea)
p1.wea.wea_attack(p1, p2)  # 通过p1.wea找到sword 然后在sword.wea_attack执行方法,其中self省略了。

6.面向对象的继承

'''
整体说明:
01 继承的作用:
    (1)节省代码
    (2)提高效率
    (3)让类之间产生关联
02 继承的分类
    (1)单继承
    (2)多继承
03 类的分类
    (1)经典类:不继承object的类。
    (2)新式类:默认继承object类
    (3)说明:python2x中经典类和新式类共存;python3x中全部都是新式类
04 在继承的时候,执行的顺序是先在子类/派生类中寻找收含有变量,如果含有则直接输出,如果不含有,则根据“类对象指针”寻找
   父级中是否含有该变量,如果有则直接输出,如果不含有,则继续寻找父级的父级中是否含有该变量,直至遍历了所有的父级类,仍
   没有则报错。
05  两种方法解决既要执行子类的方法,又要执行父类的方法
    (1)方法一:直接调用另一个类的方法
    (2)方法二:使用super() 自动将self传给父类的self
'''


# 01 单继承
'''
说明:
01 Animal是父类/基类Person是子类/派生类。
'''

#  0101 单继承说明
class Animal:
    a1 = '太白'

    def __init__(self, kind, age, sex):
        self.kind = kind
        self.age = age
        self.sex = sex

    def func1(self):
        print(666)


class Person(Animal):
    a1 = 'alex'  # 由于子类中含有该变量,所以直接输出变量值 alex,不会根据类对象指针去寻找父级类中是否含有该变量。
    pass
print(Person.a1)

# 0102 单继承说明
'''
两种解决方式解决既要执行子类的方法,又要执行父类的方法
01 第一种  Animal.__init__(self, k1, a1, s1) 直接调用另一个类的方法
02 第二种:super().__init__(k1,a1,s1)  # 自动将self传给父类的self
'''


class Animal:
    def __init__(self, kind, age, sex):
        self.kind = kind
        self.age = age
        self.sex = sex

    def bark(self):
        print('动物都会叫')


class Dog(Animal):
    def __init__(self, k1, a1, s1, bite):
        '''
        self = d1
        k1 = '藏獒'
        ....
        '''
        Animal.__init__(self, k1, a1, s1)   # 方法一:Animal.__init__(self, k1, a1, s1) 直接调用另一个类的方法
        # super().__init__(k1, a1, s1)  # 方法二: 自动将self传给父类的self
        self.bite = bite  #  新增Dog的属性,咬合力 bite

    def bark(self):
        super().bark()  # 调用父类(超类)中需要执行的动态方法。
        print('汪汪汪')


class Cat(Animal):
    def bark(self):
        print('喵喵喵')


class chick(Animal):
    def bark(self):
        print('大爷,来玩呀')

d1 = Dog('藏獒', 3, '', 300)  # 类Dog的实例化对象d1。
d1.bark()  # 对象执行类中的动态方法。

# 02 多继承
# 新式类:C3算法 mro 主要是查询 新式类的多继承的继承顺顺序

class A:
    def func(self):
        print(666)
    pass

class B:
    def func(self):
        print(666)
    pass

class C(A):
    def func(self):
        print(666)
    pass

class D(B):
    def func(self):
        print(666)
    pass

class E(C,D):
    # def func(self):
    #     print(666)
    pass

e1 = E()
# e1.func()

print(E.mro())

7.面向对象的多态

'''
整体说明:
01 Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态。
02 Java或C#中定义函数参数时,必须指定参数的类型,而python不需要强制制定数据类型。
'''

 

posted @ 2018-11-12 12:48  马玉刚  阅读(344)  评论(0编辑  收藏  举报