Python3 - self语法面向对象内置属性魔法方法
Posted 韩俊强
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python3 - self语法面向对象内置属性魔法方法相关的知识,希望对你有一定的参考价值。
文章目录
1.uuid
# uuid 用来生成一个全局唯一的id模块
# 一般而言, 在对uuid的需求不是很复杂的时候, uuid1或者uuid4方法就已经够用了
import uuid
print(uuid.uuid1()) # e703f4d4-92e3-11ec-a109-acde48001122, 32个长度 每一个字符有16个选择, 16**32选择
# print(uuid.uuid2) python 不让用
# uuid3 和 uuid5 是使用传入的字符串根据指定的算法算出来的, 是固定的
print(uuid.uuid3(uuid.NAMESPACE_DNS, 'xiaohange')) # uuid3生成固定的uuid 基于md5
print(uuid.uuid5(uuid.NAMESPACE_DNS, 'xiaohange')) # uuid5生成固定的uuid 采用散列算法sha1
print(uuid.uuid4()) # 使用的最多, 基于随机数, 每次生成不一样, 有一定概率重复的
2.使用第三方模块
pip install <package_name> 用来下载一个第三方的模块
pip uninstall <package_name> 用来删除第三方模块
pip list 用来列出当前环境安装的模块名和版本号
pip freeze 用来列出当前环境安装的模块名和版本号
临时修改, 只修改这一个文件的下载路径
pip install flask -i https://pypi.douban.com/simple/ 从指定地址下载包
pip freeze > requirements.txt 将安装的模块名和版本号重定向输出到指定的文件
pip install -r requirements.txt 读取文件里模块名和版本号并安装
python 在查找模块的时候, 在哪些路径下查找
from flask import Flask
import sys
print(sys.path)
如果模块里没有定义 all 才会导入所有不以 _ 开头的变量和函数
# 没有设置 __all__ , 会读取所有不以下划线开始的所有变量和函数
x = 'hello'
y = 1000
# 以一个下划线开始变量, 建议只在本模块里使用, 别的模块不要导入
_age = 19 # 使用from 模块名 import * 这种方式无法导入
_age += 1 # _外界就不要用我了
def _bar():
print('我是hello里的bar函数, 我只能hello文件内使用')
del (_age, _bar) # 外部不让用
# from demo import * 只会识别__all__标记的属性和函数
# from demo import n 想读到n, 也可以这样导入
__all__ = ['m', 'test']
a = 'hello'
n = 100
def test():
print('我是my_module模块里的test函数')
def add(x, y):
return x + y
from demo import *
from demo import n
print(my_module.a)
my_module.test()
print(my_module.add(10, 20))
# 使用from demo import * 写法, 不需要再写模块名
print(m)
test()
print(n)
from hello import *
print(x)
print(y)
# print(_age)
# 不建议导入_的
# import hello
# print(hello._age)
# from datetime import * # 不能导入_is_leao , 不建议在模块外使用, 否则有可能出问题
# import datetime
# datetime._is_leap(2000)
3.包的使用
可以将多个具有相似或者有关联的多个模块放到一个文件夹里, 便于统一管理; 这个文件夹, 我们就可以称之为包
# python包里, 会有一个 __init__.py 文件
from chat import recv_msg
from chat.send_msg import y
import json
import flask
print(recv_msg.x)
print(y)
import chat
print(chat.send_msg.y)
print(recv_msg.x)
4.self语法的使用
class Student(object):
__slots__ = ('name','age', 'city') # 这个属性直接定义在类里, 是一个元祖, 用来规定对象可以存在的属性
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print('大家好, 我是', self.name)
# Student('张三', 18) 具体干了什么
# 1. 调用__new__方法, 用来申请内存空间
# 2. 调用__init__方法, 并让self指向申请好的内存空间
# 3. 让变量 s1 也指向创建好的这段内存空间
s1 = Student('张三', 18)
print('0x%X' % id(s1)) # 0x7F7CA01FEFD0
s1.say_hello()
s2 = Student('赵四', 20)
s2.say_hello()
# 直接使用等号给一个属性赋值
# 如果这个属性以前不存在, 会给对象添加一个新的属性
# 动态属性
s1.city = '上海' # 给对象添加一个city属性
print(s1.city)
# 如果这个属性以前存在, 会修改这个属性对应的值
s1.name = 'jack'
print(s1.name) # jack
5.魔法方法
魔法方法, 也叫魔术方法, 是类里的特殊的一些方法
特点:
-
不需要手动调用, 会在合适的时机自动调用
-
这些方法, 都是使用__开始, 使用__结束
-
方法名都是系统规定好的, 在合适的时机自己调用
import time
import datetime
x = datetime.datetime(2022, 2, 23, 12, 13, 45, 200)
print(x) # __str__ 方法 2022-02-23 12:13:45.000200
print(repr(x)) # __repr__ 方法 datetime.datetime(2022, 2, 23, 12, 13, 45, 200)
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)
# kwargs 是一个字典 fn: lambda x, y: x + y
print('args=,kwargs='.format(args, kwargs)) # args=(1, 2),kwargs='fn': <function <lambda> at 0x7fa6100e7040>
return kwargs['fn'](args[0], args[1])
p = Person('张三', 10)
# 手动立即销毁
# del p
# 如果不做任何的修改, 直接打印这个对象, 是文件__name__.类型 内存地址
# print(p) # <__main__.Person object at 0x7febc020efd0>
# 当打印一个对象的时候, 会调用这个对象的 __str__ 或者 __repr__ 方法
# 如果两个方法都写了, 选择 __str__
print(p)
# print(repr('name': '张三', 'age': 18)) # 'name': '张三', 'age': 18
# print(repr(p)) # 'hello' 调用内置函数repr, 会触发对象的 __repr__ 方法
# print(p.__repr__()) # 魔法方法, 一般不手动的调用
# p() # 对象名() ==> 调用这个对象的 __call__ 方法
# p(1, 2) # 对象名() ==> 调用这个对象的 p.__call__(1, 2) 方法
n = p(1, 2, fn=lambda x, y: x + y)
print(n) # 3
6.运算符相关的魔法方法
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
# print('__eq__方法被调用了, other=', other) # __eq__方法被调用了, other= <__main__.Person object at 0x7fc23820ef10>
# if self.name == other.name and self.age == other.age:
# return True
# return False
return self.name == other.name and self.age == other.age
# 调用 __new__ 方法申请内存空间
p1 = Person('zhangsan', 12)
p2 = Person('zhangsan', 12)
p3 = Person('zhangsan', 13)
print(p1==p3) # False
# p1 和 p2 是同一个对象吗? 不一个地址
print('0x%X' % id(p1)) # 0x7FAE58156FD0
print('0x%X' % id(p2)) # 0x7FAE58156F10
# is 身份运算符, 可以用来判断两个对象是否是同一个对象
print('p1 is p2: ', p1 is p2) # False
# __eq__ 如果不重写, 默认比较的依然是内存地址,
print('p1==p2: ', p1 == p2) # False 本质上是调用 p1.__eq__(p2), 获取这个方法的返回值
# is 比较两个对象的内存地址
# == 会调用 __eq__ 方法, 获取这个方法的比较结果
# num1 = [1, 2, 3]
# num2 = [1, 2, 3]
# print(num1 is num2) # False
# print((num1 == num2)) # True
7.内置属性
class Person(object):
# 在创建对象时, 会自动调用这个方法
def __init__(self, name, age):
print('__init__方法被调用了')
self.name = name
self.age = age
def eat(self):
print(self.name + '正在吃饭')
p = Person('张三', '23')
print(p.__class__) # <class '__main__.Person'>
print(p.__dict__) # 'name': '张三', 'age': '23' 把对象属性的值转换为一个字典
# print(p.__dir__()) # 等价于dir(p)
print(p.__doc__) # 对象名.__doc__
print(Person.__doc__) # 类名.__doc__
print(p.__module__) # __main__
8.如何把对象当做一个字典使用
class Person(object):
type = '人类' # 这个属性定义在类里, 函数之外, 我们称之为类属性
__enname = 'person' # 私有属性
def __init__(self, name, age):
print('__init__方法被调用了')
self.name = name
self.age = age
def eat(self):
print(self.name + '正在吃饭')
def __setitem__(self, key, value):
print(f'__setitem__被调用key, value')
self.__dict__[key] = value
def __getitem__(self, item):
return self.__dict__[item]
p = Person('张三', '23')
print(p.__dict__) # 将对象转换成字典 'name': '张三', 'age': '23'
# 不能直接把字典当成字典使用
p['name'] = 'jack' # [] 语法会调用对象的 __set_item_ 方法
p['age'] = 20
print(p.name, p.age)
print(p['name']) # 会调用 __getitem__方法
print(p.type)
# print(p.__enname) 不允许访问私有属性(__属性名)
9.私有属性的使用
class Person(object):
type = '人类' # 这个属性定义在类里, 函数之外, 我们称之为类属性
__enname = 'person' # 私有属性
def __init__(self, name, age):
print('__init__方法被调用了')
self.name = name
self.age = age
def eat(self):
print(self.name + '正在吃饭')
def __setitem__(self, key, value):
print(f'__setitem__被调用key, value')
self.__dict__[key] = value
def __getitem__(self, item):
return self.__dict__[item]
p = Person('张三', '23')
print(p.__dict__) # 将对象转换成字典 'name': '张三', 'age': '23'
# 不能直接把字典当成字典使用
p['name'] = 'jack' # [] 语法会调用对象的 __set_item_ 方法
p['age'] = 20
print(p.name, p.age)
print(p['name']) # 会调用 __getitem__方法
print(p.type)
# print(p.__enname) 不允许访问私有属性(__属性名)
10.类方法和静态方法
class Calculator(object):
def __init__(self, m, n):
self.m = m
self.n = n
@staticmethod
def add(a, b):
return a + b
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self, food): # 对象方法有一个参数self, 指的是实例方法
print(self.name + '正在吃' + food)
# 如果一个方法没有用到任何的实例对象的任何属性, 可以将这个方法定义成static, 静态方法
@staticmethod
def demo(): # 默认的方法都是对象方法
print('hello')
@classmethod
def test(cls): # 如果这个函数只用到了类属性, 我们把这个定义称为一个类方法
# 类方法会有一个参数 cls, 也不需要手动传参, 会自动传参, cls指的是类对象 cls is Person
print('yes')
p = Person('张三', 18)
# 实例对象在调用方法时, 不需要给形参self传参, 会自动的把实例传递给self
p.eat('香蕉') # 直接使用实例对象调用方法
print(Person.eat(p, '香蕉')) # 使用类调用实例方法
# 静态方法: 没有用到实例对象的任何属性
Person.demo()
p.demo()
print(Calculator.add(1, 2))
# 类方法: 可以使用实例对象和类对象调用
print(Person.test())
11.面向对象练习
# 房子 有户型, 总面积, 剩余面积(等于总面积的60%)和家具的具体列表属性
# 新房子没有任何家具
# 将家具的名称追加到家具名称列表中
# 判断 家具的面积是否超过剩余面积, 如果超过, 提示不能添加这件家具
class House(object):
# 缺省参数
def __init__(self, house_type, total_area, fru_list=None):
if fru_list is None: # 如果这个值是None
fru_list = [] # 将fru_list设置为空列表
self.house_type = house_type
self.total_area = total_area
self.free_area = total_area * 0.6
self.fru_list = fru_list
def add_fru(self, x):
if self.free_area < x.area:
print('面积不足!')
else:
print(f'将x.name添加到房子里')
self.fru_list.append(x.name)
self.free_area -= x.area
def __str__(self):
return '户型=, 总面积=,剩余面积=, 家具列表='.format(self.house_type, self.total_area, self.free_area, self.fru_list)
class Furniture(object):
def __init__(self, name, area):
self.name = name
self.area = area
# 创建房间对象的时候, 传入户型和总面积
house = House('一室一厅', 20)
sofa = Furniture('沙发', 10)
bed = Furniture('席梦思', 4)
sched = Furniture('衣柜', 2)
table = Furniture('餐桌', 1.5)
# 把家具添加到房间里(面向对象关注点: 让谁做)
house.add_fru(sofa)
house.add_fru(bed)
house.add_fru(sched)
house.add_fru(table)
print(house.__str__())
print(house)
12.函数练习
# 编写一个函数, 求多个数中的最大值
import random
def get_max(*args):
x = args[0]
for arg in args:
if arg > x:
x = arg
return x
# 编写一个函数, 实现摇骰子的功能, 打印N个骰子的点数之和
def get_sum(n):
m = 0
for i in range(n):
x = random.randint(1, 6)
m += x
return m
# 编写一个函数, 提取指定字符串中所有的字母, 然后拼接在一起产生一个新的字符串
def get_alphas(word):
new_str = ''
for w in word:
if w.isalpha():
new_str += w
return new_str
# 写一个函数, 默认求10的阶乘, 也可以求其他数字的阶乘
def get_factorial(n=10):
x = 1
for i in range(1, n + 1):
x *= i
return x
# 写一个函数, 求多个数的平均值
def get_average(*args):
x = 0
for arg in args:
x += arg
return x / len(args)
# 写一个自己的capitalize函数, 能够将指定的字符串的首字母变成大写字母
def my_capitalize(word):
c = word[0]
if 'z' >= c >= 'a':
new_str = word[1:]
return c.upper() + new_str
return word
# 写一个自己的endwith函数, 判断一个字符串是否以指定的字符串结束
def my_endswith(old_str, str1):
return old_str[-len(str1):] == str1
# 写一个自己的isdigit函数, 判断一个字符串是否是纯数字字符串
def my_isdigit(old_str):
for s in old_str:
if not '0' <= s <= '9':
return False
return True
# 写一个自己的upper函数, 将一个字符串中所有的小写字母变成大写字母
# a===> 97 A ==> 65 差32
def my_upper(old_str):
new_str = ''
for s in old_str:
if 'a' <= s <= 'z':
upper_s = chr(ord(s) - 32)
new_str += upper_s
else:
new_str += s
return new_str
# 写一个函数实现自己in操作, 判断指定序列中, 指定的元素是否存在
def my_in(it, els):
for i in it:
if i == els:
return True
else:
return False
# 写一个自己的replace函数, 将指定字符串中指定的旧字符串转换成指定的新字符串
def my_replace(all_str, old_str, new_str):
# 第一种: return new_str.join(all_str.split(old_str))
# 第二种:
result = ''
i = 0
while i < len(all_str):
temp = all_str[i:i+ len(old_str)]
if temp != old_str:
result += all_str[i]
i += 1
else:
result += new_str
i += len(old_str)
return result
# 写一个自己的max函数, 获取指定序列中元素的最大值, 如果序列是字典, 取字典值的最大值
def get_max2(seq):
# if type(seq) == dict:
if isinstance(seq, dict): # 看对象seq是否是通过dict类创建出来的实例
seq =以上是关于Python3 - self语法面向对象内置属性魔法方法的主要内容,如果未能解决你的问题,请参考以下文章