Question:  How can each hue group of a seaborn.kdeplot, or seaborn.displot with kind='kde' be given a different linestyle?  Both axes-level and figure-level options will accept a str for linestyle/ls, which applies to all hue groups.    import seaborn as sns import matplotlib.pyplot as plt # load sample data iris = sns.load_dataset("iris") # convert data to long form im = iris.melt(id_vars='species') # axes-level plot works with 1 linestyle fig = plt.figure(figsize=(6, 5)) p1 = sns.kdeplot(data=im, x='value', hue='variable', fill=True, ls='-.') # figure-level plot works with 1 linestyle p2 = sns.displot(kind='kde', data=im, x='value', hue='variable', fill=True, ls='-.')   kdeplot    displot   Reviewed Questions  How to set the line style for each kdeplot in a jointgrid doesn't deal with hue groups. How to automatically alternate or cycle linestyles in seaborn regplot? doesn't deal with hue groups and iterates through each unique group. Dotted Seaborn distplot doesn't deal with hue groups and iterates through each unique group. change line style in seaborn facet grid hue_kws isn't a valid option. 

Answer:  With fill=True the object to update is in .collections With fill=False the object to update is in .lines Updating the legend is fairly simple:  handles = p.legend_.legendHandles[::-1] extracts and reverses the legend handles. They're reversed to update because they're in the opposite order in which the plot linestyle is updated Note that figure-level plots extract the legend with ._legend, with the axes-level plots use .legend_.   Tested in python 3.8.12, matplotlib 3.4.3, seaborn 0.11.2  kdeplot: axes-level  Extract and iterate through .collections or .lines from the axes object and use .set_linestyle  fill=True fig = plt.figure(figsize=(6, 5)) p = sns.kdeplot(data=im, x='value', hue='variable', fill=True) lss = [':', '--', '-.', '-'] handles = p.legend_.legendHandles[::-1] for line, ls, handle in zip(p.collections, lss, handles): line.set_linestyle(ls) handle.set_ls(ls)   fill=False fig = plt.figure(figsize=(6, 5)) p = sns.kdeplot(data=im, x='value', hue='variable') lss = [':', '--', '-.', '-'] handles = p.legend_.legendHandles[::-1] for line, ls, handle in zip(p.lines, lss, handles): line.set_linestyle(ls) handle.set_ls(ls)   displot: figure-level  Similar to the axes-level plot, but each axes must be iterated through The legend handles could be updated in for line, ls, handle in zip(ax.collections, lss, handles), but that applies the update for each subplot. Therefore, a separate loop is created to update the legend handles only once.  fill=True g = sns.displot(kind='kde', data=im, col='variable', x='value', hue='species', fill=True, common_norm=False, facet_kws={'sharey': False}) axes = g.axes.flat lss = [':', '--', '-.'] for ax in axes: for line, ls in zip(ax.collections, lss): line.set_linestyle(ls) handles = g._legend.legendHandles[::-1] for handle, ls in zip(handles, lss): handle.set_ls(ls)   fill=False g = sns.displot(kind='kde', data=im, col='variable', x='value', hue='species', common_norm=False, facet_kws={'sharey': False}) axes = g.axes.flat lss = [':', '--', '-.'] for ax in axes: for line, ls in zip(ax.lines, lss): line.set_linestyle(ls) handles = g._legend.legendHandles[::-1] for handle, ls in zip(handles, lss): handle.set_ls(ls)