python学习记录

目录

前言

MethodType

装饰器(Wrapper)

Type object class的关系

__new__()

Urllib库

UnicodeEncodeError

dict写入txt文件

相对路径和绝对路径


前言

记录自己Python学习过程中遇到的问题


MethodType

MethodType可以把外部函数(方法)绑定到类或类的实例中

MethodType(set_age,t1)第一个是实例要绑定的方法,第二个是实例。

class Student(object):
    pass
 
def set_name(self, name):
    self.name = name
def set_age(self,age):
    self.age = age

s1 = Student()
s2 = Student()
s3 = Student()
#分别给s1和s2实例绑定此方法
s1.set_name = MethodType(set_name, s1)#跟2版本相比变成两个参数,即去掉了后面的所属类参数
s2.set_name = MethodType(set_name, s2)
 
s1.set_name('s1')
s2.set_name('s2')
print(s1.name)#s1
print(s2.name)#s2
print(s3.name)#报错:AttributeError: 'Student' object has no attribute 'name'

把set_age方法用MethodType()函数绑定到Student类上,Student类的不同实例都调用的同一个set_age方法,后面的值会覆盖前面的赋值。

Student.set_age=MethodType(set_age,Student)
t1.set_age(10)
t2.set_age(11)
print (t1.age)--->11
print (t2.age)--->11

在Py3版本时,MethodType()函数只能绑定两个参数了,为了给所有实例都绑定方法,可以给class绑定方法,而可以不用MethodType()函数:

#Student.set_name=set_name
from types import MethodType
class Student(object):
    pass
def set_name(self, name):
    self.name = name
def set_age(self, age):
    self.age = age
def set_gendder(self, gender):
    self.gender = gender
s1 = Student()
s2 = Student()
t1 = Student()
t2 = Student()
# 分别给s1和s2实例绑定此方法
s1.set_name = MethodType(set_name, s1)  # 跟2版本相比变成两个参数,即去掉了后面的所属类参数
s2.set_name = MethodType(set_name, s2)
s1.set_name('s1')
s2.set_name('s2')
print(s1.name)  # s1
print(s2.name)  # s2
#print(s3.name) # 报错:AttributeError: 'Student' object has no attribute 'name'
#给类绑定方法
Student.set_age = MethodType(set_age, Student)
t1.set_age(10)
t2.set_age(11)
print(t1.age)  # 11
print(t2.age)  # 11

Student.set_gender = set_gendder
s1.set_gender('man')
print(s1.gender)
s2.set_gender('women')
print(s2.gender)

装饰器(Wrapper)

#被修饰函数带参数的装饰器
def wrapper(f):     # 装饰器函数,f是被装饰的函数
     def inner(*args,**kwargs):
         '''在被装饰函数之前要做的事'''
         ret = f(*args,**kwargs)     # 被装饰的函数
         '''在被装饰函数之后要做的事'''
         return ret
     return inner
 
 @wrapper           # 语法糖 @装饰器函数名
 def func(a,b):     # 被装饰的函数
     time.sleep(1)
     print('装饰器',a,b)
     return 'decrator'
 
 
# wraps版
from functools import wraps
 
def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

Type object class的关系

#如果想要查看一个对象是由哪个类实例化而来,可以使用type() 或 object_name.__class__来查看
class A:
    pass

a = A()

print(A.__bases__) # (<class 'object'>,)
print(object.__bases__) # ()
print(type(a)) # <class '__main__.A'>
print(type(A)) # <class 'type'>
print(type(object)) # <class 'type'>
print(type.__bases__) # (<class 'object'>,)
  1. 如果定义一个类时没有指定继承哪个类,则默认继承object类
  2. object类的父类为空,说明object类位于继承关系链的顶端,object类是Python中所有类的父类,可以说object是python中的顶端类
  3. 对象a由类A实例化而来,a的类型为A,这个比较容易理解。
  4. 根据3的观察结果,同样的观察手法运用在类A上,观察到类A是由type这个类实例化而来,类A的类型为type,说明类A是一个类的同时也是一个对象(类A是类type的实例化对象)。这里可能有点晕但是请先接着看下去吧。
  5. 根据3的观察结果,同样的观察手法运用在顶端类object上,观察到object这个顶端类也是由type这个类实例化而来,类object的类型也为type,也说明object作为一个类的同时也是一个对象。
  6. 类`type`作为实例化类`A`和类`object`的类,其父类为`object`

    下面我们就可以开始看图写作文啦~

    蓝色箭头由实例对象指向实例化它的类,红色箭头由子类指向父类。值得注意的是,这个图有几个关键的地方:

  • 类(如class A, class object)都是由type这个类实例化而来的,即所有类(class)对象的类型都是type
  • type这个类也是由type自己实例化而来的(图中type处指向自身的部分),即type类的类型也为type
  • type类的父类是object类

有了以上的铺垫,我们可以知道一个最普通的实例对象链是这样子的:

type --实例化--> object --衍生--> class --实例化--> a(具体对象)

__new__()

只有继承于object的新式类才能有__new__方法,__new__方法在创建类实例对象时由Python解释器自动调用,一般不用自己定义,Python默认调用该类的直接父类的__new__方法来构造该类的实例,如果该类的父类也没有重写__new__,那么将一直按此规矩追溯至object的__new__方法,因为object是所有新式类的基类,若需要自定义__new__方法,一般用法如下:

class Person(object):
    def __new__(cls):
        return  object.__new__(cls)
#__new__(cls[,...])的参数说说起,__new__方法的第一个参数是这个类,
#而其余的参数会在调用成功后全部传递给__init__方法初始化

__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供;__new__必须要有返回值,返回实例化出来的实例,可以return父类new出来的实例,或直接是object的new出来的实例。若__new__()没有正确返回当前类cls的实例,那__init__()将不会被调用

class Dog(object):
    def __init__(self):
        self.name="旺财"
        print("Dog.__init__")
class Person(object):
    def __init__(self):
        self.name="张三"
        print("Person.__init__")
    def __new__(cls):
        print('__new__')
        ob = object.__new__(Dog)
        return ob
p1 = Person()
print(type(p1))
#__new__
#<class '__main__.Dog'>

Urllib库

urllib — URL handling modules — Python 3.10.2 documentation

urllib中包括了四个模块,包括:urllib.requesturllib.errorurllib.parseurllib.robotparser

UnicodeEncodeError

    在test.py保存的时候,会按照系统编码方式GBK的方式(有的编辑器也能自定义编码格式),编码成gbk二进制码流,存储到磁盘上。当运行该程序时。gbk二进制码流调入内存,并按照python设置的解码方式解码,也就是按照UTF-8的方式解码,所以结果不是错误提示,就是显示出来的是乱码
    这就是说开始用utf-8编码,后面写入文件的时候没有设置解码方式,系统默认是gbk解码,而gbk是utf-8的子集,所以出现上面的错误。因此我只需要设置一下写入时的编码方式就可以了。

with open('网页源代码.html','w',encoding='utf-8')as f:

dict写入txt文件

import urllib.request
import urllib.parse
import json
url = 'https://fanyi.baidu.com/sug'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 Edg/98.0.1108.56'
}
data = {
    'kw':'spider'
    }
data = urllib.parse.urlencode(data).encode('utf-8')
#请求的参数必须进行编码 encode方法
request = urllib.request.Request(url=url,data=data,headers=headers)
response = urllib.request.urlopen(request)
contnet = response.read().decode()
obj = json.loads(contnet)
#dic = {'name': 'Su', 'gender': 'female','age':20}
#1.将dict序列化后写入,需要用到json的damps()函数对数据进行编码,其返回值是’str‘类型:
#2. 如果dict中存在中文,用以上方法会出现以下结果:
## {"\u59d3\u540d": "Su", "\u6027\u522b": "\u5973", "age": 20}
# 为避免这种情况,需要对以上damps方法中的参数进行设置。先来看看damps函数的源代码:#
# def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
#         allow_nan=True, cls=None, indent=None, separators=None,
#         default=None, sort_keys=False, **kw)
# 其中ensure_ascii用来规定返回值是否可以包含非ASCII码。中文超过ASCII码范围,所以会出现以上乱码情况。

with open('post请求方式.txt','w',encoding='utf-8') as fp:
    fp.write(json.dumps(obj,ensure_ascii=False))


相对路径和绝对路径

绝对路径就是文件的真正存在的路径,是指从硬盘的根目录(盘符)开始,进行一级级目录指向文件。相对路径就是以当前文件为基准进行一级级目录指向被引用的资源文件。

比如脚本在C:/python目录下,相同目录下有一个文件叫test.txt,那么绝对路径就是C:/python/test.txt,相对路径就是test.txt

#新建 目录 文件夹下新建cheshi.txt
import os
os.mkdir('目录')
file = open('目录/cheshi.txt','w')
file.close()

path = 'dataset'
# 创建文件夹
if not os.path.exists(path):
    os.mkdir(path)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值