[IOS]——新浪微博发微博的实现(纯文字)

效果图

%title插图%num
代码实现
//https://api.weibo.com/2/statuses/share.json
NSMutableString *string = [[NSMutableString alloc] initWithString:@”设置你所需要的参数(详细看上面给出的微博文档)格式为 https://api.weibo.com/2/statuses/share.json?access_token=你的应用的访问授权&status=你要发送的文本内容”];
//拼接
NSString *newstr = [NSString stringWithFormat:@”%@ http://www.mob.com”,self.textView.text];
NSString *str1 = [NSString stringWithFormat:@”%@%@”,string,newstr];
//将字符串中的特殊字符进行转码
NSString *str2 = [str1 stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@”`#%^{}\”[]|\\<> “].invertedSet];
//创建url
NSURL *accurl = [NSURL URLWithString:str2];
//创建请求
NSMutableURLRequest *accrequest = [[NSMutableURLRequest alloc]initWithURL:accurl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
//改变请求方式为post
[accrequest setHTTPMethod:@”POST”];
//设置请求体(POST请求一定要设置请求体)
NSString *str = @”type=focus-c”;//设置参数
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
[accrequest setHTTPBody:data];
//连接服务器
NSData *received = [NSURLConnection sendSynchronousRequest:accrequest returningResponse:nil error:nil];
NSError *error;
if(received){
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:received options:NSJSONReadingMutableContainers error:&error];
NSLog(@”%@”,dictionary);

[IOS]——懒加载要注意的问题

问题一——判断是否为空时出现无限循环问题
在if判断语句中-if(_musicArray)是为了判断数组是否为空,为空时就加载数据,要注意的是:这里使用( _musicArray下划线的形式,而不是self.musicArray的形式。因为懒加载其实是在重写get方法,那么用self.musicArray那就会无限调用调用get方法)

%title插图%num
问题二:关于NavigationController页面跳转时出现的加载问题
由于导航控制器自带返回功能,因此这是收藏列表这个控制器还没有销毁,所以说里面的数据是仍然存在的。但我当点击爱心图标取消收藏再回到收藏列表时应该会把这首歌的数据删除掉的,但是我们发现那首歌依然在。

%title插图%num
原因在于:懒加载的问题——由于收藏列表的控制器没有被销毁,所以里面的数据还在,因此使用懒加载时只会加载原来的数据,而不是新数据
解决办法:
把if的判断语句去掉,这时候只要回到该控制器,数据有改变时就会刷新

%title插图%num

 

python受欢迎的原因是什么?

python受欢迎的原因是什么?

在过去的一年里,美国人用金枪鱼搜索python而不是
Kim kardashian,其背后的主要原因是python的简单性和灵活性。它已经为那些难以编程的人提供了编码指尖。它是开源的。我们可以免费下载 。

这里出现了一些问题:

是什么让python简单易学?是什么让它与其他编程语言不同?它受欢迎的原因是什么?

它的语法简单明了,易于阅读。

它使用缩进空格,使代码易于理解。

它有145,000个自定义构建的软件包,从开发应用程序,游戏开发到天文学,上传到在线存储库。

它还可以用作服务器来创建网站,系统脚本,软件开发,数学等。

它被谷歌,YouTube,Spotify,皮克斯,雅虎和更多网站使用。

python能做什么?

它可以读取和修改文件。它可以连接到数据库系统。

它用于解决复杂的数学问题,它可以处理大数据。

我们也可以用它来进行快速原型制作。

所以*后,我想说有很多原因让python与其他语言不同并影响人们使用它,使它如此受欢迎。

我们可以在不同的平台上使用python,如Windows,Mac,Linux等。

它的语法类似英语语言允许程序员编写比其他语言更少的代码行。它支持多种范例,如程序,功能和面向对象。

如何利用Python播放和录制声音

如何利用Python播放和录制声音

如果您想使用Python播放或录制声音,那么您来对地方了!在本教程中,您将学习如何使用一些*流行的音频库在Python中播放和录制声音。您将了解*直接的播放和录制声音的方法,然后您将了解一些提供更多功能的库,以换取一些额外的代码行。

在本教程结束时,您将了解如何:
播放MP3和WAV文件,以及一系列其他音频格式

播放包含声音的NumPy和Python数组

使用Python录制声音

以各种不同的文件格式保存录制文件或音频文件

播放音频文件
下面,您将看到如何使用一系列Python库播放音频文件。其中一些库允许您播放一系列音频格式,包括MP3和NumPy阵列。下面的所有库都允许您播放WAV文件,其中一些代码行代码比其他文件更多:

playsound如果你只是想播放WAV或MP3文件,是*简单的包。除简单播放外,它不提供任何功能。

simpleaudio 让您播放WAV文件和NumPy数组,并为您提供检查文件是否仍在播放的选项。

winsound 允许您播放WAV文件或发出哔哔声,但它仅适用于Windows。

python-sounddevice并pyaudio为PortAudio库提供绑定,以便跨平台播放WAV文件。

pydub需要pyaudio进行音频播放,但ffmpeg安装后,只需几行代码即可播放各种音频格式。

让我们一起来看看这些用于音频播放的库。

playsound
playsound是一个“纯Python,跨平台,单一功能模块,不依赖于播放声音。” 使用此模块,您可以使用一行代码播放声音文件:

from playsound import playsound

该文件中playsound指出,它已在WAV和MP3文件进行测试,但它可能对其他文件格式正常工作。

该库*后更新于2017年6月。在撰写本文时似乎运行良好,但目前尚不清楚它是否仍然支持更新的Python版本。

simpleaudio
simpleaudio是一个跨平台的库,用于播放没有依赖关系的(单声道和立体声)WAV文件。以下代码可用于播放WAV文件,并在终止脚本之前等待文件完成播放:

import simpleaudio as sa
filename = ‘myfile.wav’
wave_obj = sa.WaveObject.from_wave_file(filename)
play_obj = wave_obj.play()
play_obj.wait_done() # Wait until sound has finished playing

WAV文件包含表示原始音频数据的一系列位,以及具有 RIFF(资源交换文件格式)格式的元数据的标题。

对于CD录制,行业标准是将每个音频样本(与气压相关的单个音频数据点)存储为16位值,每秒44100个样本。

为了减小文件大小,以较低的采样率存储一些记录(例如人类语音)可能就足够了,例如每秒8000个样本,尽管这确实意味着较高的声音频率可能没有准确表示。

本教程中讨论的一些库播放和记录bytes对象,而其他库使用NumPy数组来存储原始音频数据。

两者都对应于一系列数据点,这些数据点可以以指定的采样率播放以播放声音。对于bytes对象,每个样本存储为一组两个8位值,而在NumPy数组中,每个元素可以包含对应于单个样本的16位值。

这两种数据类型之间的一个重要区别是bytes对象是不可变的,而NumPy数组是可变的,使后者更适合生成声音和更复杂的信号处理。有关如何使用NumPy的更多信息,请查看我们的NumPy教程。

simpleaudio允许您使用NumPy和Python数组和bytes对象simpleaudio.play_buffer()。确保安装了NumPy以使以下示例正常工作simpleaudio。(pip安装后,您可以通过pip install numpy从控制台运行来执行此操作。)

有关如何使用pip安装包的更多信息,

下面你将看到如何生成一个对应于440 Hz音调的NumPy数组并使用simpleaudio.play_buffer()以下方式播放:

import numpy as np
import simpleaudio as sa

frequency = 440 # Our played note will be 440 Hz
fs = 44100 # 44100 samples per second
seconds = 3 # Note duration of 3 seconds

# Generate array with seconds*sample_rate steps, ranging between 0 and seconds
t = np.linspace(0, seconds, seconds * fs, False)

# Generate a 440 Hz sine wave
note = np.sin(frequency * t * 2 * np.pi)

# Ensure that highest value is in 16-bit range
audio = note * (2**15 – 1) / np.max(np.abs(note))
# Convert to 16-bit data
audio = audio.astype(np.int16)

# Start playback
play_obj = sa.play_buffer(audio, 1, 2, fs)

# Wait for playback to finish before exiting
play_obj.wait_done()

接下来,让我们看看如何winsound在Windows机器上播放WAV文件。

winsound
如果使用Windows,则可以使用内置winsound模块访问其基本的声音播放机器。播放WAV文件可以在几行代码中完成:

import winsound

filename = ‘myfile.wav’
winsound.PlaySound(filename, winsound.SND_FILENAME)

winsound不支持播放WAV文件以外的任何文件。它确实允许您使用扬声器发出哔哔声winsound.Beep(frequency, duration)。例如,您可以使用以下代码将1000 Hz音调发出100毫秒的响声:

import winsound
winsound.Beep(1000, 100) # Beep at 1000 Hz for 100 ms

接下来,您将学习如何使用该python-sounddevice模块进行跨平台音频播放。

python-sounddevice
正如其文档中所述,python-sounddevice“为PortAudio库提供绑定,并提供一些便利功能来播放和记录包含音频信号的NumPy数组”。为了播放WAV文件,numpy而且soundfile需要安装,打开WAV文件作为NumPy的阵列。

随着python-sounddevice,numpy以及soundfile安装,您现在可以读取WAV文件作为与NumPy阵列和回放:

import sounddevice as sd
import soundfile as sf
filename = ‘myfile.wav’
# Extract data and sampling rate from file
data, fs = sf.read(filename, dtype=’float32′)
sd.play(data, fs)
status = sd.wait() # Wait until file is done playing

该行包含sf.read()提取原始音频数据,以及存储在其RIFF标题中的文件的采样率,并sounddevice.wait()确保脚本仅在声音播放完毕后终止。

接下来,我们将学习如何使用pydub播放声音。通过安装正确的依赖项,它允许您播放各种音频文件,并为您提供更多的音频处理选项python-soundevice。

pydub
虽然pydub可以在没有任何依赖性的情况下打开和保存WAV文件,但您需要安装音频播放包才能播放音频。simpleaudio强烈建议,但是pyaudio,ffplay和avplay有其他选择。

以下代码可用于播放WAV文件pydub:

from pydub import AudioSegment
from pydub.playback import play
sound = AudioSegment.from_wav(‘myfile.wav’)
play(sound)

为了播放其他音频类型,如MP3文件,ffmpeg或者libav应该安装。看一看在文档中pydub的说明。作为文档中描述的步骤的替代,ffmpeg-python提供绑定ffmpeg,并可以使用pip安装:

$ pip install ffmpeg-python
1
随着ffmpeg安装,播放MP3文件,只需要在我们的前面的代码一个小的变化:

from pydub import AudioSegment
from pydub.playback import play

sound = AudioSegment.from_mp3(‘myfile.mp3′)
play(sound)

使用该AudioSegment.from_file(filename, filetype)结构,您可以播放任何类型的支持音频文件ffmpeg。例如,您可以使用以下方式播放WMA文件:

sound = AudioSegment 。from_file (’myfile.wma’ , ‘wma’ )
1
除了播放声音文件之外,还pydub可以使用不同的文件格式保存音频(稍后会详细介绍),切片音频,计算音频文件的长度,淡入或淡出以及应用交叉淡入淡出。

AudioSegment.reverse()创建一个向后播放的AudioSegment的副本,该文档描述为“对Pink Floyd有用,可以使用,以及一些音频处理算法”。

pyaudio
import pyaudio
import wave

filename = ‘myfile.wav’

# Set chunk size of 1024 samples per data frame
chunk = 1024

# Open the sound file
wf = wave.open(filename, ‘rb’)

# Create an interface to PortAudio
p = pyaudio.PyAudio()

# Open a .Stream object to write the WAV file to
# ‘output = True’ indicates that the sound will be played rather than recorded
stream = p.open(format = p.get_format_from_width(wf.getsampwidth()),
channels = wf.getnchannels(),
rate = wf.getframerate(),
output = True)

# Read data in chunks
data = wf.readframes(chunk)

# Play the sound by writing the audio data to the stream
while data != ”:
stream.write(data)
data = wf.readframes(chunk)

# Close and terminate the stream
stream.close()
p.terminate()

您可能已经注意到,播放声音pyaudio比使用您之前看到的库播放声音要复杂一些。这意味着如果您只想在Python应用程序中播放声音效果,它可能不是您的首选。

但是,由于pyaudio为您提供了更多的低级控制,因此可以为输入和输出设备获取和设置参数,并检查CPU负载和输入或输出延迟。

它还允许您在回调模式下播放和录制音频,其中当需要播放或可用于录制时需要新数据时调用指定的回调函数。pyaudio如果您的音频需求不仅仅是简单的播放,这些选项可以使用合适的库。

现在您已经了解了如何使用许多不同的库来播放音频,现在是时候看看如何使用Python自己录制音频了。

录制音频
在python-sounddevice和pyaudio库提供的方式来录制音频和Python。python-sounddevice记录到NumPy数组和pyaudio记录到bytes对象。这两个都可以分别使用scipy和wave库存储为WAV文件。

python-sounddevice
python-sounddevice允许您录制麦克风的音频并将其存储为NumPy阵列。这是一种方便的声音处理数据类型,可以使用该scipy.io.wavfile模块转换为WAV格式进行存储。确保安装scipy以下示例的模块(pip install scipy)。这会自动将NumPy安装为其依赖项之一:

import sounddevice as sd
from scipy.io.wavfile import write

fs = 44100 # Sample rate
seconds = 3 # Duration of recording

myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2)
sd.wait() # Wait until recording is finished
write(‘output.wav’, fs, myrecording) # Save as WAV file

pyaudio
在本文的前面部分,您学习了如何通过阅读来播放声音pyaudio.Stream()。录制音频可以通过写入此流来完成:

import pyaudio
import wave

chunk = 1024 # Record in chunks of 1024 samples
sample_format = pyaudio.paInt16 # 16 bits per sample
channels = 2
fs = 44100 # Record at 44100 samples per second
seconds = 3
filename = “output.wav”

p = pyaudio.PyAudio() # Create an interface to PortAudio

print(‘Recording’)

stream = p.open(format=sample_format,
channels=channels,
rate=fs,
frames_per_buffer=chunk,
input=True)

frames = [] # Initialize array to store frames

# Store data in chunks for 3 seconds
for i in range(0, int(fs / chunk * seconds)):
data = stream.read(chunk)
frames.append(data)

# Stop and close the stream
stream.stop_stream()
stream.close()
# Terminate the PortAudio interface
p.terminate()

print(‘Finished recording’)

# Save the recorded data as a WAV file
wf = wave.open(filename, ‘wb’)
wf.setnchannels(channels)
wf.setsampwidth(p.get_sample_size(sample_format))
wf.setframerate(fs)
wf.writeframes(b”.join(frames))
wf.close()

现在您已经了解了如何用python-sounddevice和记录音频pyaudio,您将学习如何将录音(或任何其他音频文件)转换为一系列不同的音频格式。

保存和转换音频
您之前看到可以使用该scipy.io.wavfile模块将NumPy阵列存储为WAV文件。该wavio模块同样允许您在WAV文件和NumPy数组之间进行转换。如果您想以不同的文件格式存储音频,pydub并且soundfile派上用场,因为它们允许您读取和写入一系列流行的文件格式(例如MP3,FLAC,WMA和FLV)。

wavio
此模块依赖于numpy并允许您将WAV文件读取为NumPy阵列,并将NumPy阵列保存为WAV文件。

要将NumPy数组保存为WAV文件,您可以使用wavio.write():

import wavio

wavio.write(“myfile.wav”, my_np_array, fs, sampwidth=2)

在此示例中,my_np_array包含音频的NumPy数组fs是记录的采样率(通常为44100或44800 Hz),并且sampwidth是音频的采样宽度(每个采样的字节数,通常为1或2个字节)。

soundfile
该soundfile库可以读写所有支持的文件格式libsndfile。虽然它无法播放音频,但它允许您将音频转换为FLAC,AIFF和一些不太常见的音频格式。要将WAV文件转换为FLAC,可以使用以下代码:

import soundfile as sf

# Extract audio data and sampling rate from file
data, fs = sf.read(‘myfile.wav’)
# Save as FLAC file at correct sampling rate
sf.write(‘myfile.flac’, data, fs)

类似的代码将用于转换支持的其他文件格式libsndfile。

pydub
pydub让您以任何ffmpeg支持的格式保存音频,其中包括您日常生活中可能遇到的几乎所有音频类型。例如,您可以使用以下代码将WAV文件转换为MP3:

from pydub import AudioSegment
sound = AudioSegment.from_wav(‘myfile.wav’)

sound.export(‘myfile.mp3′, format=’mp3’)

使用AudioSegment.from_file()是一种加载音频文件的更通用的方法。例如,如果要将文件从MP3转换回WAV,可以执行以下操作:

from pydub import AudioSegment
sound = AudioSegment.from_file(‘myfile.mp3′, format=’mp3’)

sound.export(‘myfile.wav’, format=’wav’)

此代码应适用于任何格式的音频文件是ffmpeg支持。

结论:在Python中播放和录制声音
在本教程中,您学习了如何使用一些*流行的音频库来播放和录制Python中的音频。您还了解了如何以多种不同格式保存音频。

你现在能够:

播放各种音频格式,包括WAV,MP3和NumPy阵列
将麦克风的音频录制到NumPy或Python阵列
将录制的音频存储为各种格式,包括WAV和MP3
将声音文件转换为一系列不同的音频格式

如何集成Python代码和GUI来创建一个简单的游戏?

如何集成Python代码和GUI来创建一个简单的游戏?

您不需要集成任何内容。您可以使用pygame屏幕作为GUI。

公平警告:它没有内置功能,如按钮或弹出窗口。每次都需要硬编码。

通过集成,如果你的意思是python代码的结果应该显示在屏幕上,那么这将发生。如果要将另一个python文件导入pygame文件,只需在文件顶部输入import filename即可。

如果你的意思是象国际象棋所需的复杂的GUI,那么我担心这是不可能的。我建议在Javascript中使用它。

你如何在python中创建GUI?

要显示图像:

import pygame
pygame.init()
#制作屏幕
SCR_WIDTH = 800
SCR_HEIGHT = 600
screen = pygame.display.set_mode((SCR_WIDTH, SCR_HEIGHT))
#制作图像对象(确保图像存在于同一目录中)
racecar = pygame.image.load(‘racecar.png’)
#然后你需要在屏幕上粘贴图像:
screen.blit(racecar, (0, 0))
#after pasting image you need to update the screen
pygame.display.update()

你必须制作一个游戏循环,让pygame窗口退出运作。

running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()

如何制作按钮?

制作按钮要困难得多。即使是悬停效果也必须进行硬编码。你制作的“按钮”真是假的,只是看起来和功能就像一个按钮。你需要制作一个盒子或形状,然后在屏幕上显示它,然后获得鼠标的位置。如果鼠标的位置在形状内,则在按钮的图像上显示另一个图像以获得悬停效果。当光标离开按钮内部时,您需要重新显示按钮的原始图像。

if 150+100 > mouse[0] > 150 and 450+50 > mouse[1] > 450:
pygame.draw.rect(gameDisplay, bright_green,(150,450,100,50))
else:
pygame.draw.rect(gameDisplay, green,(150,450,100,50))
pygame.draw.rect(gameDisplay, red,(550,450,100,50))
pygame.display.update()

android OKHTTP文件下载工具类

AndroidOkhttp下载文件工具类

在使用okhttp前需要添加okhttp包,如下:

*好加上权限:

private static final String[] REQUIRED_PERMISSIONS = new String[]{
“android.permission.READ_EXTERNAL_STORAGE”,
“android.permission.WRITE_EXTERNAL_STORAGE”,
“android.permission.READ_PHONE_STATE”,
“android.permission.INTERNET”,

};
/**
* 初始化获取权限
*/
public void initPer() {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
List<String> lackedPermission = new ArrayList<String>();
for (String PER : REQUIRED_PERMISSIONS) {
if (!(getActivity().checkPermission(PER, Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED)) {
lackedPermission.add(PER);
}
}
if (lackedPermission.size() > 0) {
getActivity().requestPermissions(lackedPermission.toArray(new String[lackedPermission.size()]), 1024);
}
}
}
回调代码:

private void downFile(String url, String filepath, String filename) {
DownloadUtil.get().download(url, filepath, filename,
new DownloadUtil.OnDownloadListener() {
@Override
public void onDownloadSuccess(File file) {
//下载成功
Log.i(“LZ—“, “onDownloadSuccess:……. ………………文件下载成功…………………………”);
//下载成功后需要做的事
}

@Override
public void onDownloading(int progress) {
//下载中
Log.i(“LZ—“, “onDownloading:…………………………文件下载中…………………………..”);
}

@Override
public void onDownloadFailed(Exception e) {
//下载异常进行相关提示操作
Log.e(“lz—“, “onDownloadFailed:……………………..下载文件失败………………………….”);
//文件下载失败之后的处理

}
});
}
调用下载

/*@
* 文件下载 url:地址 filepateh: 存放文件路径 filename: 文件名字(需要自行添加下载后的后缀名,)
*
*/

String dirName = MainActivity.this.getCacheDir().getPath();
downFile(“下载url”, “下载存放的路径dirName “, “fullvideo.mp4”);
工具类,

/**
* Created by Admin on 2021/3/3.
*/
public class DownloadUtil {
private static DownloadUtil downloadUtil;
private final OkHttpClient okHttpClient;

public static DownloadUtil get() {
if (downloadUtil == null) {
downloadUtil = new DownloadUtil();
}
return downloadUtil;
}

/**
* 文件下载路径
*android 10以后文件读写权限又更改,判断系统属于android10以上还是android10以下,更换路径
*/
public String DownFullVideoPath(Context context) {
String dirName;
// String dirName = context.getExternalCacheDir().getAbsolutePath();
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= 29) {
dirName = context.getExternalCacheDir().getPath();

return dirName;
} else if (currentapiVersion < 29) {
dirName = context.getExternalCacheDir().getAbsolutePath();
return dirName;
}
return “”;
}

public DownloadUtil() {
okHttpClient = new OkHttpClient();
}

/**
* @param url 下载连接
* @param destFileDir 下载的文件储存目录
* @param destFileName 下载文件名称,后面记得拼接后缀,否则手机没法识别文件类型
* @param listener 下载监听
*/
public void download(final String url, final String destFileDir, final String destFileName, final OnDownloadListener listener) {
Request request = new Request.Builder()
.url(url)
.build();
OkHttpClient client = new OkHttpClient();
try {
Response response = client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}

//异步请求
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 下载失败监听回调
listener.onDownloadFailed(e);
}

@Override
public void onResponse(Call call, Response response) throws IOException {

InputStream is = null;
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fos = null;

//储存下载文件的目录
File dir = new File(destFileDir);
dir.delete();
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, destFileName);
Log.e(“lz—-:”, ” ” + file);
try {

is = response.body().byteStream();
long total = response.body().contentLength();
fos = new FileOutputStream(file);
long sum = 0;
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
sum += len;
int progress = (int) (sum * 1.0f / total * 100);
//下载中更新进度条
listener.onDownloading(progress);
}
fos.flush();
//下载完成

listener.onDownloadSuccess(file);
} catch (Exception e) {
listener.onDownloadFailed(e);
} finally {

try {
if (is != null) {
is.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException e) {

}
}
}
});
}

public interface OnDownloadListener {

/**
* 下载成功之后的文件
*/
void onDownloadSuccess(File file);

/**
* 下载进度
*/
void onDownloading(int progress);

/**
* 下载异常信息
*/

void onDownloadFailed(Exception e);
}
}
这样一个简单的下载工具就完成了。

 

-END

 

为什么Python如此受欢迎?

为什么Python如此受欢迎?

Python很慢和/或它不是的两个*常见的原因高性能:

解读
GIL
*个是相当直接的,但在高级别编译器将更高级别的语言翻译成更低级别(更快)的语言,因此编译语言几乎总是比非编译语言执行得更快。这个经验法则有一些例外(例如JIT可能比AOT编译更快的情况),但它们会分散讨论。

第二个是更臭名昭着,但是Python有一个叫做全局解释器锁的东西,它通过强制解释器一次只在一个进程(Python解释器的实例)中执行单个线程来基本上防止多线程。它的工作原理也很有趣,但也像编译器一样切入兔子洞。

Python性能下降9/10倍并不重要。

随着时间的推移,我认为有两个主要原因。

首先,重要的不是代码执行时间,而是*终用户体验。它不一般的问题,如果一个函数具有0.001秒或0.01来执行。在这种情况下,对于大多数问题,可以使用水平扩展来解决Python创建的许多瓶颈。

以这些基准为例对于流行的Web框架。使用Python的*好的是650.5K req / s,而*好的数字是2.2M。纯粹从性能的角度来看,你可能想知道为什么你不会选择*快的,但是你看看那个#1点并意识到它正在使用C. C是一种很棒的语言(IMO),但是Python很多更具表现力,拥有更大的生态系统,您可以选择使用预先构建的工具。因此,在牺牲开发时间/范围的同时,不是从服务器中挤出*后一点计算能力,而是可以为每1个需要C的服务器获得4台Python服务器,并节省开发人员生产力和开发时间的许多倍。这显然是一个戏剧性和*其简化的例子,但我认为这一点是合理的。

这让我们围绕GIL的第二个实现和我的结论,它确实并没有那么糟糕。

通过不允许多线程(或在同一进程中同时执行),Python大大简化了开发人员面临的编程复杂性。 开发人员可以忽略多线程进程的常见 问题和优化,因为Python解释器一次只能执行一个逻辑。

这也通常不会多大关系为同一水平推理点1而不是解决与多线程问题,您可以选择与解决问题的多重处理。您可以启动多个进程并在它们之间进行通信,而不是在单个进程中管理多个线程。差异很微妙,但同样,对于这些情况中的9/10,多处理与线程的性能开销并不重要。

在头顶性能的情况下做的事情,你可以随时“胶水”不同的语言为你的Python逻辑。典型的例子是Numpy如何通过放入C将高性能数组结构数据结构带到Python。

那么这一切又是什么呢?

随着计算能力(处理器核心的数量,单个核心的速度,服务器硬件的成本等)越来越便宜,大多数性能问题通常可以通过水平扩展来解决。

对于你无法横向解决的事情,你可以用不同的语言写一些东西并将其“粘合”到你的Python逻辑中(假设Python是一种“胶水”语言)。

因此,如果*终可以增强/处理性能,那么您需要将Python作为一种语言的主要原因:

简单
生产的
可读(从而更易于维护)

关于Python的优点和缺点,我们可以谈论更多的内容,我们可以更详细地讨论,但我认为这是解决为什么Python解释器性能不会影响其受欢迎程度的问题的良好开端。

 

什么是Python中的map,reduce和filter?

什么是Python中的map,reduce和filter?

基本上,lambdas以及map,reduce和filter为python提供了函数式编程能力。让我们看看他们是什么。

map: map函数采用 iterable(list,tuple,set)并将函数应用于列表中的每个元素。让我们看一个例子来看看它是如何工作的。
任务1:给定一个整数列表,编写代码,以方的所有数s在列表中。

def func (num ):
“””
对给定数字进行平方的函数
“””
return num * num

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

#map采用一个函数并应用于
#列表中的每个元素
ans = list (map (func ,l ))

#[1,4,9,16,25,36]
print(ans)

上面的代码工作并执行我们想要实现的内容,但我们可以使用lambda函数以更简洁的方式编写它,而不是创建单独的函数。让我们稍微改变一下代码,使其更简洁。

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

#[1,4,9,16,25,36]
ans = list (map (lambda x :x * x ,l ))
print(ans)

任务2:给定一个整数列表,编写一个代码来均数偶数,但将奇数数字排成一行。这里我们可以一起使用map和lambda,如下所示

l = [1, 2, 3, 4, 5, 6]
ans = list(map(lambda x: x ** 2 if x % 2 == 0 else x ** 3, l))
print(ans)
1
2
3
这总结了地图的基本工作。我们来看看过滤器

filter:它的工作原理类似于map函数。顾名思义,它用于根据特定条件过滤元素。不同之处在于它从列表中的元素创建满足某些条件的新列表。让我们看看它如何与一个例子一起工作。这些参数类似于地图的参数。它需要一个谓词函数和一个可迭代函数。
任务3:给定一个整数列表,编写一个代码,仅从列表中分隔偶数。

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

#只保留满足谓词功能的列表元素
ans = list(filter(lambda x: x % 2 == 0, l))

# [2, 4, 6]
print(ans)

reduce:它继续在列表中应用函数,直到它返回单个值。让我们通过一个例子来看看reduce的工作
任务4:给定一个整数列表,编写一个代码,返回通过乘以列表中的元素获得的总值。

from functools import reduce

l = [1, 2, 3, 4, 5, 6]
ans = reduce(lambda x, y: x * y, l)
print(ans)

笔记:

map和 filter返回一个map对象,而 reduce返回一个值。
我们必须从functools导入reduce,但map和filter可直接在builtins中使用

Python:为什么必须在方法定义和调用中明确使用’self’?

Python:为什么必须在方法定义和调用中明确使用’self’?

面向对象的语言有对象。对象是状态和行为的组合。对象需要访问自己的状态。这样做基本上有两个主要选择。要么你明确地说你何时访问一个对象的状态(通过self,this或者其他类似的东西),或者语言会为你找出。

让我先讨论后一种情况。存在名称冲突的问题。例如,如果对象的数据成员与方法参数的名称匹配,或者如果声明与数据成员的名称匹配的局部变量,会发生什么。您要么不允许这种情况,要么具有某种解决机制。Smalltalk是一个像这样工作的语言的例子,但我不记得语言是如何处理碰撞问题的。

在大多数OOP语言,当你从它的一个方法中引用一个对象的状态(或其他方式),你明确地说,就是你用做什么自我,或者这个,或者别的什么东西。这种功能的语言有两种形式。他们要么隐式地这样做 – 这意味着你不必声明链接实体(就像C ++那样)或者你明确地声明它(比如Python)。

请记住,在Python 中调用此链接实体self纯粹是一种约定; 所有程序员都应该遵循的有用约定,但仍然只是一个约定。你可以称之为,或州或我或任何东西,但这将是愚蠢的。该语言的作用是将调用对象显式传递给每个方法作为*个参数,该参数用于访问状态和其他方法。

*后,Python使用self的方式是一种有利于(如Tony Flury所说)明确的设计决策。我相信很多人都有关于这是一个好的决定还是其他方面的想法。我的意见是,这是一个很好的。

如何用二元分类器解决一个多分类任务?

Tips | 如何用二元分类器解决一个多分类任务?

二元分问题会是我们生活中比较常见的一类问题,比如邮件可以分为垃圾邮件和非垃圾邮件、一个人患病或者不患病,但除此之外也会遇到一些多元分类问题,比如天气可以分为晴、阴、雨、雪等等。

我们通过算法构建的分类器就以分为二元分类器和多元分类器,前者可以区分两个类别标签,后者则可以区分两个以上的类别标签。对于算法而言,像SVM、逻辑回归等是严格的二元分类算法,而像朴素贝叶斯、随机森林这类算法则可以直接处理多元分类问题。但利用二元分类器处理多分类问题是可行的,下面将以逻辑回归结合鸢尾花数据集为例介绍。

OvA、OvO策略
利用二元分类器解决多分类问题可以分为两种策略:

one-versus-all(OvA)策略,也可以称one-versus-rest(OvR),简称一对多。
one-versus-one(OvO)策略,简称一对一,应该有人用OvO当过文字表情吧。
用过鸢尾花数据集的伙伴应该知道这份数据集的类别标签共有三类,分别是山鸢尾(setosa)、变色鸢尾(versicolor)和维吉尼亚鸢尾(virginica),因为有三个类别嘛,所以就构造三个二元分类器,假设为山-分类器、变-分类器和维-分类器。训练时将某个类别的样本归为一类,其余类别的样本归为另一类,这样对于某个未知类别的样本,三个分类器都会有一个决策分数(概率),然后取*高决策分数的一个类别作为该样本的类别,这种方式就属于一对多法。

而一对一的做法是构建多个任意两类样本间的二元分类器,原理类似于组队,比如上述三个标签变量可以组成山和变、山和维、变和维,如果类别为n的话,需要的分类器个数为 n ( n − 1 ) 2 \frac{n(n-1)}{2}
2
n(n−1)

。*后也是取决策分数*高的一个类别作为某个未知类别的样本*终分类。

从上面介绍中也很容易可得出两者的优缺点:

OvA缺点:因为是一个类别对多个类别(1:N的关系),所以在训练时可能会更偏向多类别的一方。
OvA优点:假设有n个类别,只需要构建n个分类器。
OvO缺点:在标签类别很多的情况下,需要构建很多个二元分类器,不论构建还是训练的过程都比较麻烦
OvO优点:每个分类器只需要在包含两个类别的部分数据上训练,无需在整个数据集上。
这两种策略的基本思想都是通过构建多个二元分类器来解决多分类问题。大多数二元分类算法比较适用OvA策略,当然并不是全部,并且还需要根据数据集的特点而定。下面利用逻辑回归在鸢尾花数据集上建模,因为数据集比较简单,我们又是只讲这种方法,所以省略掉了分析之类的操作。

手推实现OvA策略
我个人会习惯将数据集转化为容易观察的DataFrame格式:

import pandas as pd
from sklearn.datasets import load_iris
feature_names = load_iris().feature_names
dataset_data = pd.DataFrame(load_iris().data,columns=feature_names)
dataset_target = pd.DataFrame(load_iris().target,columns=[‘target’])
data = pd.concat([dataset_data,dataset_target],axis = 1)

数据集共有150个样本、四个特征和一个类别标签:

我们采用一对多(OvA策略)结合逻辑回归解决这个多分类问题,先介绍一下手推的方式,建模过程与二分类是一样的,只不过我们需要注意一下OvA策略的思想。

首先需要划分数据集,取七份作为训练集,剩余三份为测试集,基础部分就不贴代码啦,文末会给出完整代码获取方式。OvA策略是有多少个类别就构建多少个分类器,所以需要知道标签变量所有类别,可以利用unique索引,然后利用字典格式存储所有的分类器。

#获取标签变量的类别
unique_targets = data[‘target’].unique()
”’
array([0, 1, 2])
”’
# 采用OvA策略,三个类别对应三个模型,用字典格式存储
models = {}

每一个分类器都会把一个类别归为一类,剩余的类别归为另一类,所以这里暂定每次循环和target相同的为一类,标签设为1,剩余的两类标签设为0。为了代码的简洁度,这里利用了管道流将每个分类器和标准化处理封装起来。

y_train_copy = y_train.copy()
for target in unique_targets:
#管道流封装
models[target] = make_pipeline(StandardScaler(),LogisticRegression())
y_train_list = y_train_copy.tolist()
# 每次都要修改训练集的标签,将当前类别的标签设为1,其它类别设为0
for i in range(len(y_train_list)):
if y_train_list[i] == target:
y_train_list[i] = 1
else:
y_train_list[i] = 0
y_train = np.array(y_train_list)

models[target].fit(X_train,y_train)

创建相应的分类器之后,下面需要做的就是在测试集上应用,三个分类器*终会得到三个标签的预测概率。

test_probs = pd.DataFrame(columns=unique_targets)
for target in unique_targets:
#[:,1]返回的是属于1的概率,[:,0]是属于0的概率
test_probs[target] = models[target].predict_proba(X_test)[:,1]
print(test_probs)

可以得到的关于概率的DataFrame如下:

在pandas中有一个idxmax()方法可以索引出一个样本中值*大的列索引,在这里就是一个样本*终被划分的类别。

predicted_target = test_probs.idxmax(axis=1)
”’
0 0
1 0
2 1
3 0
4 2
5 1
…….
模型错误率为:6.67%
”’

*后可以通过和原标签比对计算出模型的准确率,至此就是如何利用二元分类器实现多元分类问题的手推方法。

sklearn调用
在sklearn中也有可以实现OvA和OVO策略的类,和手推方法相比会更加简单便捷,分别为OneVsOneClassifier或OneVsRestClassifier。

from sklearn.multiclass import OneVsOneClassifier,OneVsRestClassifier
OvO = OneVsOneClassifier(make_pipeline(StandardScaler(),LogisticRegression()))
OvO.fit(X_train,y_train)
ovo_predict = OvO.predict(X_test)

对于这类库的调用应该都比较熟悉,不在过多介绍,利用相应的方法可以查看类标签和分类器的个数,3个类别比较巧,OvA和OvO两个策略所需构建二元分类器的个数都为3个。

print(‘类别标签有:%s’ % OvO.classes_)
print(‘分类器个数:%d’ % len(OvO.estimators_))
”’
类别标签有:[0 1 2]
分类器个数:3
”’

其实在逻辑回归的multi_class参数中,就有ovr(OvA)这个策略可供选择,但是没有OvO策略。毕竟手推的方式会更容易帮助理解一个策略的思想,理解之后我们再调用类或者调参时才会知道究竟做的是什么操作,综上就是关于如何利用二分类算法解决多元分类问题的概述。

参考链接:
[1].https://blog.csdn.net/zm714981790/article/details/51243955