python-11-面对对象基础

01-uuid模块

# uuid用来生成一个全局唯一的id
import uuid

print(uuid.uuid1())  # 32个长度  每一个字符有16个选择  16**32
# print(uuid.uuid2())

# uuid3和uuid5是使用传入的字符串根据指定的算法算出来的,是固定的
print(uuid.uuid3(uuid.NAMESPACE_DNS, 'zhangsan'))  # 生成固定的uuid
print(uuid.uuid5(uuid.NAMESPACE_DNS, 'zhangsan'))  # 生成固定的uuid

print(uuid.uuid4())  # 使用的最多

这个好像没啥用(目前作者自己还没用到)

02-使用第三方模块

# Python在查找模块的时候,在哪些路径下查找?

from flask import Flask
import sys

print(sys.path)

sys.path——>查找路径

03-使用自定义模块

# 一个模块本质上就是一个py文件
# 自己定义一个模块,其实就是自己写一个py文件
# import 04-我的模块   如果一个py文件想要当做一个模块被导入,文件名一定要遵守命名规范
# 由数字、字母下划线组成,不能以数字开头

# 导入了一个模块,就能使用这个模块里变量和函数
import my_module

# 使用 from <module_name> import * 导入这个模块里"所有"的变量和函数
# 本质是读取模块里的 __all__ 属性,看这个属性里定义了哪些变量和函数
# 如果模块里没用定义 __all__ 才会导入所有不以 _ 开头的变量和函数
from demo import *

print(my_module.a)
my_module.test()
print(my_module.add(1, 2))

# 使用from demo import * 写法,不再需要写模块名
print(m)
test()

import demo

print(demo.n)

from hello import *

print(x)
print(y)
# print(_age)

import hello

# print(hello._age)

# hello._bar()
# print(hello.x)

# import datetime
# datetime._is_leap(2000)

04-包的使用

# 可以将多个具有相似或者有关联的多个模块放到一个文件夹里,便于统一管理
# 这个文件夹,我们就可以称之为包
# python包里,会有一个 __init__.py 文件

from chat import recv_msg
from chat.send_msg import x
import json
import flask

import chat

print(recv_msg.y)
print(x)
print(chat.recv_msg.y)

05-面向过程

def add_user():
    pass


def del_user():
    pass


def modify_user():
    pass


def query_user():
    pass


def show_all():
    pass


def start():
    while True:
        print("""---------------------------
        名片管理系统 V1.0
    1:添加名片
    2:删除名片
    3:修改名片
    4:查询名片
    5:显示所有名片
    6:退出系统
    ---------------------------""")
        operator = input('请输入要进行的操作(数字)')
        if operator == '1':
            add_user()
        elif operator == '2':
            del_user()
        elif operator == '3':
            modify_user()
        elif operator == '4':
            query_user()
        elif operator == '5':
            show_all()
        elif operator == '6':
            pass
        else:
            print('输入有误,请重新输入......')


if __name__ == '__main__':
    start()

06-面向对象的基本语法

# 小明今年 18 岁,身高 1.75,每天早上跑完步,会去 吃 东西
# 小美今年 17 岁,身高 1.65,小美不跑步,小美喜欢 吃 东西

# 定义类:类名怎么定义? 使用 class 来定义一个类
# class 类名:类名一般需要遵守大驼峰命名法,每一个单词的首字母都大写
# 1. class <类名>:
# 2. class <类名>(object):


class Student(object):  # 关注这个类有哪些特征和行为
    # 在 __init__ 方法里,以参数的形式定义特征,我们称之为属性
    def __init__(self, name, age, height):
        self.name = name
        self.age = age
        self.height = height

    # 行为定义为一个个函数
    def run(self):
        print('正在跑步')

    def eat(self):
        print('正在吃东西')


# 使用 Student 类创建了两个实例对象 s1 s2
# s1和s2都会有name,age,height属性,同时都有run和eat方法
s1 = Student('小明', 18, 1.75)  # Student() ==> 会自动调用 __init__ 方法
s2 = Student('小美丽', 17, 1.65)

# 根据业务逻辑,让不同的对象执行不同的行为
s1.run()
s1.eat()

s2.eat()

07-self语句的使用

class Student(object):
    # 这个属性直接定义在类里,是一个元组,用来规定对象可以存在的属性
    __slots__ = ('name', 'age', 'city')

    def __init__(self, x, y):
        self.name = x
        self.age = y

    def say_hello(self):
        print('大家好,我是', self.name)


# Student('张三',18) 这段代码具体做了什么呢?
# 1. 调用 __new__ 方法,用来申请内存空间
# 2. 调用 __init__ 方法传入参数,将 self 指向创建好的内存空间,填充数据
# 3. 变量 s1 也指向创建好的内存空间
s = Student('张三', 18)

print(s.name)
s.say_hello()

# 没有属性,会报错
# print(s.height)

# 直接使用等号给一个属性赋值
# 如果这个属性以前不存在,会给对象添加一个新的属性
# 动态属性
s.city = '上海'  # 给对象添加了一个city属性
print(s.city)

# 如果这个属性以前存在,会修改这个属性对应的值
s.name = 'jack'
print(s.name)  # jack
# Student('张三',18) 这段代码具体做了什么呢?
# 1. 调用 __new__ 方法,用来申请内存空间
# 2. 调用 __init__ 方法传入参数,将 self 指向创建好的内存空间,填充数据
# 3. 变量 s1 也指向创建好的内存空间
s = Student('张三', 18)

天我们要说的是面向对象的核心-----类,类能帮我们把复杂的事情变得有条理,有顺序,希望大家通过学习类能改善自己的编码风格,使代码变得更为好看,更加通俗易懂。

1.类的用法

一、什么是类

类(class),作为代码的父亲,可以说它包裹了很多有趣的函数和方法以及变量,下面我们试着简单创建一个吧。

这样就算创建了我们的第一个类了。大家可以看到这里面有一个self,其实它指的就是类aa的实例。每个类中的函数只要你不是类函数或者静态函数你都得加上这个self,当然你也可以用其他的代替这个self,只不过这是python中的写法,就好比Java 中的this。

二、类的方法

1.静态方法,类方法,普通方法

类一般常用有三种方法,即为static method(静态方法),class method(类方法)和self(普通方法)。下面我们来看看他们之间的区别吧。

从这里可以看出我们的三种方法有一个共同点,那就是既可以在实例中访问,也可以直接用类访问。不同的是,类实例访问时是不会执行init方法的,也就是没有进行初始化。如果用类直接访问,可以清楚看到它的运行轨迹。如果想在一个方法里调用其他方法则只需:实例名.方法名 或者 类名.方法名 即可。

2.安全方法,私有方法,安全变量,私有变量

安全方法一般是为了保护类的安全性,为了限制访问权限而设立的。一般只需在方法前加单下划线即可,那么私有方法怎么访问呢?和其他方法访问方法一样。

安全方法:可以在外部进行调用并且其他方法也能访问到,它允许本身的任何方法进行访问,并可在外部调用,安全属性也是;

私有方法:只能在私有方法内部调用,不能通过类名或者类的实例名来调用,所以你可以在其他方法中通过self.ww来调用或者cls.ww来调用,这样就做到了私有的功能。

三、类的特性

类的特性,相信接触过面向对象的小伙伴应该都知道,封装、继承和多态。

1.封装

讲的就是将一个功能封装到类中,这个很好理解。

2.继承

就是一个类和另一个类的主体结构一致,就好比父亲和儿子的区别,儿子继承父亲所有的特点,这使得他可以少做一些重复劳动,并且他还有自己的一套,这就叫继承,下面我们通过实例说明:

可以看出我们实现了继承,就是简单的在子类中添加了父类的名字,并且写了个spuer,用来继承父类的所有的特性。虽然父类的所有东西我们都能继承,但并不是说所有的你都能用的,比如说父类的私有方法或者私有属性:

那么如果你想要使用它们那该怎么办呢?很简单,你只需将私有方法或者属性添加到父类某个可以公开访问的类中,然后子类就能使用这些父类定义的私有方法或者属性了。

当然,除了单一继承,还有多继承,它可以继承两个类的所有属性和方法,只不过写法与其他编程语言有点不同,它的多继承就是递归继承,不能同时继承,也就是:

这样就实现了多继承,多继承可以大大简化代码量。我们可以通过一些魔法方法来获得父类的名称以及说明。

__bases__#查看类的所有父类__base__ #查看类的父类__doc__ #查看类的使用文档,在类中以三引号扩起来的部分都是文档内容

我们注意到,只需继承一个类就实现了多继承,这是因为son类之前继承过father类,所以现在你必须通过son类继承father类,后面给它初始化,如果是两个没有任何关联的类,则需要写两个类名进去,并且初始化。

3.多态

多态的应用使得类更灵活,它可以共享某个方法,给所有的类对象使用。我们来看看:

这里是通过对一个函数传一个对象,使得它拥有了类的特征功能,这也就是鸭子类型。

4.动态修改值

当一个类需要大量创建实例时,可以通过魔法方法slots来声明。这样可以减少内存消耗。但是它只是动态的修改,并没有绑定到类的实例中,而且类只能访问slots里设定的值。

可以看到访问不了值,因为没有这个属性,我们再来看看没slots的时候:

现在正常了,另外,子类的slots为它本身和父类的slots,父类只是本身。这样极大省内存,但是这样好像还不够Python,因为他的局限性,让我决定使用property。property有两种创建方式,我们来看看:

一、装饰器

直接在方法上运用装饰器,十分方便。他有设置,获取,删除三个属性,例如:

可以看到,非常简单就实现了功能,少写了很多代码哦。

二、在类中定义值为property对象的类属性

使用property函数来实现:

可以看到,这样就实现,那么现在我们写一个稍微复杂点的,可以进行交互的动态修改属性吧。

可以看到,我输入属性名和属性值,如果你想做的更好,可以给它加其他功能,比如私有方法私有属性,访问其他类。总之功能多多,需要你自己动手亲自实践。

四、总结

通过对类的解读,让大家明白了,代码的简洁美观有多重要,为了我们的程序不那么low,请学好类。

-------------------End -------------------

08-魔术方法

# 魔法方法,也叫魔术方法,是内里的特殊的一些方法
# 特点:
# 1.不需要手动调用,会在合适的时机自动调用
# 2. 这些方法,都是使用 __ 开始,使用 __ 结束
# 3. 方法名都是系统规定好的,在合适的时机自己调用
# import datetime
#
# x = datetime.datetime(2020, 2, 24, 16, 17, 45, 200)
# print(x)  # __str__ 方法
# print(repr(x))  # __repr__ 方法


class Person(object):
    def __init__(self, name, age):
        # 在创建对象时,会自动调用这个方法
        print('__init__方法被调用了')
        self.name = name
        self.age = age

    def __del__(self):
        # 当对象被销毁时,会自动调用这个方法
        print('__del__ 方法被调用了')

    def __repr__(self):
        return 'hello'

    def __str__(self):
        return '姓名:{},年龄:{}'.format(self.name, self.age)

    def __call__(self, *args, **kwargs):
        # print('__call__ 方法被调用了')
        # args = (1, 2, 4, 5),kwargs = {'m':'good', 'n':'hehehe', 'p':'heiheihei'}
        print('args={},kwargs={}'.format(args, kwargs))


p = Person('zhangsan', 18)

# 如果不做任何的修改,直接打印一个对象,是文件的 __name__.类型 内存地址
# print(p)  # <__main__.Person object at 0x00000217467AEA08>

# 当打印一个对象的时候,会调用这个对象的 __str__ 或者 __repr__ 方法
# 如果两个方法都写了,选择 __str__
print(p)

# print(repr(p))  # 调用内置函数 repr 会触发对象的 __repr__ 方法
# print(p.__repr__())  # 魔法方法,一般不手动的调用

p(1, 2, 4, 5, m='good', n='hehehe', p='heiheihei')  # 对象名() ==> 调用这个对象的 p.__call__() 方法

09-__eq__方法介绍

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        # print('__eq__方法被调用了,other=', other)
        # if self.name == other.name and self.age == other.age:
        #     return True
        # return False
        return self.name == other.name and self.age == other.age


p1 = Person('zhangsan', 18)
p2 = Person('zhangsan', 18)
p3 = Person('zhangsan', 19)

# p1 和 p2 是同一个对象吗?
# 怎样比较两个对象是否是同一个对象?比较的是内存地址
print('0x%X' % id(p1))  # 0x20CE2A8EE88
print('0x%X' % id(p2))  # 0x20CE2A8EF08

# is 身份运算符 可以用来判断两个对象是否是同一个对象
print('p1 is p2', p1 is p2)  # False

# __eq__ 如果不重写,默认比较依然是内存地址
print('p1 == p2', p1 == p2)  # p1 == p2本质是调用 p1.__eq__(p2),获取这个方法的返回结果
print(p1 == p3)

# is 比较两个对象的内存地址
# == 会调用对象的 __eq__ 方法,获取这个方法的比较结果
# nums1 = [1, 2, 3]
# nums2 = [1, 2, 3]
# print(nums1 is nums2)  # False
# print(nums1 == nums2)  # True

10-一些demo

__all__ = ['m', 'test']
m = 'yes'
n = 100


def test():
    print('我是demo模块里的test方法')


def foo():
    print('我是demo模块里的foo方法')


def division(a, b):
    return a / b


# __name__:当直接运行这个py文件的时候,值是__main__
# 如果这个py文件作为一个模块导入的时候,值是文件名
if __name__ == '__main__':
    print('demo里的name是:', __name__)
    print('测试一下division函数,结果是:', division(4, 2))
# 没有设置 __all__ 会读取除了以_开始的所有变量和函数
x = 'hello'
y = 1000

# 以一个下划线开始变量,建议只在本模块里使用,别的模块不要导入
_age = 19  # 使用from 模块名 import * 这种方式无法导入
_age += 1


def _bar():
    print('我是hello里的bar函数,我只能hello文件内部使用')


del (_age, _bar, x)
a = 'hello'


def test():
    print('我是my_module模块里的test函数')


def add(x, y):
    return x + y
pip install <package_name>  用来下载一个第三方的模块
pip uninstall <package_name>  用来删除第三方模块
pip list 用来列出当前环境安装的模块名和版本号
pip freeze  用来列出当前环境安装的模块名和版本号

阿里云服务器   从阿里镜像下载
腾讯云服务器   从腾讯镜像下载
临时修改,只修改这一个文件的下载路径
pip install <package_name> -i <url>  从指定的地址下载包

pip freeze > file_name  将安装的模块名和版本号重定向输出到指定的文件
pip install -r file_name  读取文件里模块名和版本号并安装
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老板来片烤面包

君子博学于文,赠之以礼,谢君~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值